Free tools Windows power users keep installed
One-click scans. No signup required.
Set the limit where the workload is launched: use ulimit for a temporary shell test, PAM limits for login sessions, and systemd Limit* directives for services. Check the effective limit on the actual process, because an interactive terminal and a systemd daemon can have different values. New settings take effect only when a new session or service process starts, and a soft limit can never exceed its hard limit or the kernel ceiling.
Need a server to try this on? Antihost offers Linux VPS plans with NVMe storage, full root access and a 14-day free trial.
What ulimit controls
Linux resource limits are attached to each process. The shell’s ulimit command displays or changes the limits inherited by programs that the shell starts. A child created with fork() inherits its parent’s limits, and those limits remain in place when the child replaces its program image with execve(). This is why the command used to launch a process matters more than a system-wide setting.
As an Amazon Associate I earn from qualifying purchases.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Inheritance also explains why a limit can appear correct in one process and wrong in another. If a shell starts a wrapper, and the wrapper starts the server, the server normally receives the wrapper’s limits. If a supervisor starts the server independently, it receives the supervisor’s launch context instead. A limit is therefore part of the process startup contract, not a property that the kernel automatically synchronizes across all processes owned by an account.
Soft and hard limits
- Soft limit: the value the process currently enforces for a resource. A process can usually lower its soft limit, and an unprivileged process can raise it only up to its hard limit.
- Hard limit: the upper bound for the soft limit. Raising a hard limit requires the appropriate privilege and must also fit within any kernel ceiling.
For open files, ulimit -n addresses RLIMIT_NOFILE. The limit is a per-process allowance, not a promise that the kernel has already opened that many files or that every process on the server receives the same value. A higher allowance does not allocate file descriptors in advance; it only permits the process to acquire more when its workload needs them.
#1 Best Overall
Keep the distinction visible while troubleshooting. A configuration may raise the hard limit while leaving the soft limit lower, or a process may have inherited a lower hard limit before it reached the application. Always inspect both values in the context that launches the workload.
Measure the limit that actually applies
Measure before changing anything. Run these commands in the shell that will launch the workload:
Recommended Free Tools
ulimit -a
ulimit -Sn # soft open-file limit
ulimit -Hn # hard open-file limit
The two open-file values tell you whether the requested change is possible in that shell. If the soft value is already at the hard value, a non-privileged shell cannot raise it further. Save the output before making a change so you can distinguish an effective increase from a merely edited configuration file.
Inspect a running daemon
A terminal’s value does not prove that a daemon has the same limit. For a running process, inspect the kernel’s view:
cat /proc/<pid>/limits
Read the Max open files row and compare it with the service manager’s configuration. This check is decisive when a service is started by systemd, a supervisor, a container entrypoint, or another account rather than from your terminal.
Use the process ID of the workload that is actually accepting connections or doing the constrained work. Looking at a short-lived launcher, a parent shell, or an old main PID can give a misleading result. After a restart, obtain the new PID again and repeat the check.
Choose the launch layer
Use one layer for the workload instead of changing unrelated global settings. The following distinctions prevent the most common “my limit.conf change did nothing” failures.
| Method | Scope | Persistence | What must be restarted | Privilege | Inheritance |
|---|---|---|---|---|---|
Shell ulimit |
Current shell and programs it launches | Temporary | Launch the program from the modified shell | Soft limit can be raised only up to the existing hard limit | Children inherit the shell’s limits across fork() and execve() |
| PAM limits files | Login sessions | Persistent configuration for future sessions | Log out and start a new login session | Root access is needed to edit the files; the PAM stack must load pam_limits.so |
Programs launched in that session inherit the session limits |
systemd Limit* directives |
The service process and its descendants | Persistent unit configuration | Reload systemd and restart the service | Root access is normally needed to install the drop-in and restart the unit | Service children inherit the unit’s limits |
The table’s scope is the practical decision rule. A shell command is ideal for an isolated experiment, PAM is appropriate when users start programs through login sessions, and a systemd directive is the authoritative setting for a systemd unit. Applying a correct setting at the wrong layer still produces no change in the target process.
Test a higher limit temporarily in a shell
A temporary change is the safest way to determine whether an application benefits from a larger limit before making it persistent.
- Check the current values and record them:
ulimit -Snandulimit -Hn. - Set a test soft limit no higher than the hard limit:
ulimit -n 65536
- Verify the result with
ulimit -Sn. If the shell reports “operation not permitted,” inspect the hard limit and kernel ceiling before trying a larger number. - Start the server from that same shell, or replace the shell with it:
exec ./your-server
The exec form ensures that the tested process occupies the shell’s process slot and receives its limits. Closing the shell, opening another terminal, or starting the program through a different supervisor does not carry this temporary setting over.
This test changes the shell and its descendants only. It does not rewrite the login-session defaults, the systemd unit, or processes that were already started. If the server forks workers after launch, those workers inherit the tested value from their parent.
Set limits for login sessions with PAM
/etc/security/limits.conf and files in /etc/security/limits.d/ are read by the PAM pam_limits module when a login session is created. These values are per-session; they are not global kernel settings and do not rewrite processes that are already running.
Create a focused limits file
Put an application-specific rule in a separate file so it can be audited and changed without editing the main file. For example, create /etc/security/limits.d/90-example.conf with:
appuser soft nofile 65536
appuser hard nofile 65536
Each line follows the format <domain> <type> <item> <value>:
domainidentifies the account or other login domain to which the rule applies.typeissoftorhard.itemnames the resource, such asnofile.valueis the numeric limit.
Use the narrowest account or group scope that meets the requirement. Giving every login the same high limit makes capacity and compatibility problems harder to see. Set both soft and hard values deliberately: setting only a hard value can leave applications running at a lower soft value until they raise it themselves.
Confirm PAM is using the module
The relevant login stack must include pam_limits.so. Check the PAM configuration used by the login method, for example:
grep -R "pam_limits.so" /etc/pam.d
Different login paths can use different PAM stacks, so verify the one that creates the session in question. A rule in limits.d cannot affect a service that never enters that PAM login path.
Start a new session before verifying
Log out and log back in as the affected account, then run:
ulimit -Sn
ulimit -Hn
An existing terminal retains the limits with which it was created. Restarting a shell inside that same session does not make PAM recalculate the session’s limits; create a genuinely new login session. If a graphical login, SSH login, or another route is involved, verify that route specifically rather than assuming all sessions use identical PAM configuration.
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minuteSet limits for a systemd service
A daemon launched by systemd does not inherit the limits shown by your terminal. Configure the unit itself, preferably with a drop-in so package updates do not overwrite the change.
Create the drop-in
Open the service’s drop-in editor:
sudo systemctl edit your-service.service
Add the resource-specific directive under [Service]:
[Service]
LimitNOFILE=65536
LimitNOFILE= corresponds to the open-file limit exposed by ulimit -n. Other resources use their own directives, including LimitNPROC= for process count, LimitSTACK= for stack size, LimitCORE= for core dumps, and LimitMEMLOCK= for locked memory.
Put the directive in the service section, not in a shell profile. A profile affects an interactive login; the unit drop-in travels with the service definition and is applied whenever systemd creates a new service process.
Apply and verify the unit setting
- Reload unit configuration:
sudo systemctl daemon-reload
- Restart the service so a new process receives the limit:
sudo systemctl restart your-service.service
- Find the service’s main process and inspect its effective limit:
pid=$(systemctl show -p MainPID --value your-service.service)
cat /proc/$pid/limits | grep -i 'open files'
Always verify the process after the restart. A syntactically valid drop-in can still target the wrong unit, be superseded by another configuration layer, or be irrelevant if the workload forks a separate process under a different manager. If the service has restarted again, repeat the PID lookup before drawing a conclusion.
Why “operation not permitted” appears
When a command such as ulimit -n 1000000 fails, check both limits and the kernel ceiling:
ulimit -Hn
cat /proc/sys/fs/nr_open
- If the requested soft value is above the shell’s hard value, an unprivileged process cannot raise it.
- If the requested value is above
/proc/sys/fs/nr_open, it exceeds the kernel’s maximum forRLIMIT_NOFILE, even when the caller has privilege. - If both checks allow the value, make sure the process is being launched through the layer you changed. A PAM rule does not alter a systemd service, and a shell change does not alter an already-running daemon.
Changing the hard limit also requires privilege at the point where the process is launched. Do not treat a larger number in a configuration file as proof that the daemon received it; confirm the value in /proc/<pid>/limits. The kernel ceiling is separate from the service’s configured value, so a unit can be configured with a number that still cannot be granted if it exceeds fs.nr_open.
High nofile values and select(2) compatibility
Raising the soft open-file limit above 1024 can expose an application compatibility problem. On Linux, select(2) cannot operate on descriptors above 1023. A service that still uses select() may fail or behave incorrectly when it receives file descriptors in that range, even though the higher resource limit itself was accepted.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Before adopting a high value, confirm that the application and its libraries use descriptor APIs that support the expected range. This warning is about descriptor numbers, not only the count of simultaneously open files: an application can encounter a descriptor above 1023 once the process has opened and closed enough files. Consequently, a low descriptor count at the instant you inspect it does not by itself prove that a high soft limit is safe for code based on select().
Systemd documentation describes 524288 as a modern historical default hard nofile value in its documentation, but that figure is not a universal recommendation for every distribution or workload. Treat it as documentation context, not a target. Test the application at the proposed value and watch for descriptor-related errors before making the change permanent.
Tune other resources with the same method
The workflow is the same for process counts, stack size, core dumps, and locked memory:
- Measure the effective soft and hard values in the actual launch context.
- Identify the resource-specific name, such as
nproc,stack,core, ormemlock. - Change the shell, PAM rule, or systemd directive that launches the workload.
- Start a new session or restart the service.
- Inspect the resulting process rather than relying on the configuration file alone.
For example, a systemd service can use LimitNPROC= when process creation is constrained, while a login-session rule would use the corresponding resource item in the limits-file syntax. Raise only the resource that is demonstrably constraining the workload. Increasing unrelated limits expands the failure surface without fixing the observed bottleneck.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Rank #4
How to choose a value without guessing
There is no universal “correct” server value for nofile or nproc. Size a limit from the workload’s observed behavior:
- Measure the descriptors and processes used during normal and peak concurrency.
- Allow headroom for connection bursts, log rotation, sockets, pipes, and other descriptors the application opens in addition to its primary data files.
- Compare the proposed value with the application’s descriptor APIs, especially if it may use
select(). - Keep the hard limit high enough for the intended soft value, but avoid setting every resource to
unlimited; that can hide a capacity leak or remove a useful failure boundary. - Document which account, unit, and launch path owns the setting so a later operator does not test the wrong process.
Use a staged change: record the baseline, apply a temporary value where possible, exercise normal and peak behavior, then persist the smallest value that covers the measured need. Recheck after deployment because wrappers, service managers, and worker processes can each create a different launch context.
A limit should prevent avoidable exhaustion without masking an application that leaks descriptors or creates unbounded processes. Monitoring and application-level limits remain necessary after the kernel limit is raised. A larger ceiling is not a substitute for finding why descriptors or processes continue to grow.
Operational checklist
- Identify the exact process and the component that launches it.
- Read its effective limits from
/proc/<pid>/limits, and record the shell’s soft and hard values when testing interactively. - Choose only the matching layer: shell, PAM, or systemd.
- Check the hard limit and
/proc/sys/fs/nr_openbefore requesting a largernofilevalue. - Apply the change, create a new login session or restart the service, and obtain the new process ID.
- Verify the effective value and exercise the workload, including descriptor-heavy and peak-concurrency paths.
- Document the account, unit, value, and compatibility decision, especially whether the application can safely handle descriptors above 1023.
Common failure modes and fixes
“I edited limits.conf, but ulimit -n is unchanged.”
The terminal may predate the edit, the login stack may not load pam_limits.so, or the process may not be a PAM login at all. Create a new login session, verify the PAM module, and inspect the actual daemon if a service manager launches it.
“My terminal shows 65536, but the daemon still shows a small value.”
The daemon was launched by systemd or another supervisor. Set the unit’s LimitNOFILE=, reload systemd, restart the service, and read /proc/$pid/limits for the new process.
“The service did not change after I edited the unit.”
Editing a drop-in does not alter an existing process. Run systemctl daemon-reload followed by systemctl restart, then verify the new main PID’s limits.
“The shell refuses a value below the kernel ceiling.”
Compare the requested value with ulimit -Hn. If the hard limit is lower, the shell lacks permission to raise it. If the hard limit is high but the request exceeds /proc/sys/fs/nr_open, the kernel ceiling is the blocker.
“The application breaks after increasing nofile.”
Check whether it relies on select(2). Descriptors above 1023 are outside Linux select()‘s supported range. Roll back the high soft limit for that application or move it to compatible descriptor APIs before raising the limit again.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchFrequently asked questions
How do I increase ulimit just for one test?
In the shell that will launch the program, run ulimit -n 65536, verify with ulimit -Sn, and start the program from that same shell. The setting ends with the shell and does not affect other terminals or services.
Why does limits.conf not work for my service?
PAM limits apply to login sessions. A systemd service normally needs a unit drop-in with LimitNOFILE= or the relevant Limit* directive. Restart the service and inspect its process rather than checking an unrelated login shell.
Best Value
- New
- Mint Condition
- Dispatch same day for order received before 12 noon
- Guaranteed packaging
- No quibbles returns
How do I set the open-file limit for a systemd service?
Run sudo systemctl edit your-service.service, add LimitNOFILE=65536 under [Service], run sudo systemctl daemon-reload, and restart the service. Confirm the new value in /proc/<pid>/limits.
Why does ulimit -n say “operation not permitted”?
The requested soft value may exceed the current hard limit, or it may exceed /proc/sys/fs/nr_open. An unprivileged process cannot raise its hard limit. Check both values and ensure the change is made in the launch layer that controls the target process.
Free tools Windows power users keep installed
One-click scans. No signup required.
Does changing a limit update already-running processes?
No. Limits are inherited when a process is created. Log out and back in for PAM changes, or reload and restart a systemd service. Existing shells and daemons retain their original values.
Is 65536, or 524288, the correct value for every server?
No. Those are examples and documentation figures, not universal recommendations. Measure descriptor and process usage, add workload headroom, check application compatibility, and choose the smallest value that covers normal and peak behavior.
Can I set every resource to unlimited?
You can remove useful capacity boundaries by doing so, and you may conceal descriptor leaks or unbounded process creation. Raise only the constrained resource and keep an intentional hard limit.
What should I check after a successful change?
Verify the effective soft and hard values on the actual process, confirm the process is the new post-restart PID, and exercise the workload at realistic concurrency. For high nofile values, specifically confirm that the application does not depend on Linux select() with descriptors above 1023.
Reference manuals
The process-inheritance rules are documented in the Linux man-pages getrlimit(2) manual. Login-session syntax and scope are documented in Linux-PAM’s limits.conf(5). Service-level resource directives and the select(2) warning are documented in systemd’s systemd.exec(5). Consult the versions installed for your distribution when directive names or defaults differ.
Frequently Asked Questions
How do I increase ulimit for a one-time test?
Set the soft value in the launching shell, verify it, and start the application from that same shell. The change is temporary and affects only that shell and its children.
Why did editing limits.conf not change my daemon?
PAM limits apply to newly created login sessions. A daemon started by systemd needs a unit-level LimitNOFILE= or another appropriate Limit* directive, followed by daemon-reload and a service restart.
How can I verify the limit a service really received?
Find the service’s current PID and read /proc/
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchPC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11What causes ulimit -n to return operation not permitted?
The requested value may exceed the process’s hard limit or the kernel’s /proc/sys/fs/nr_open ceiling. Raising a hard limit also requires the appropriate privilege.
Why can a high nofile value break an application?
Linux select(2) cannot operate on descriptors above 1023. Applications that still use select() must be tested or moved to compatible descriptor APIs before adopting a soft limit above 1024.
The Bottom Line
Tune ulimit at the process launch layer: shell for a temporary experiment, PAM for future login sessions, and systemd Limit* directives for managed services. Check both soft and hard values, respect fs.nr_open, restart the session or service, and verify /proc/<pid>/limits. Choose a workload-sized value and confirm that high descriptor numbers are compatible with the application.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Recommended Free Tools




