Fixing "Too many open files" - Resolving File Descriptor Exhaustion
What You Will Solve Here
- Understand the two FD limits (per-process EMFILE vs system-wide ENFILE) and which one you hit
- Use
ulimitandlsofto check current FD usage immediately - Permanently raise limits via
limits.conf,sysctl.conf, or a systemd unit override
Fastest path (3 steps)
ulimit -nor/proc/<pid>/limitsto identify which ceiling you hitlsof -p <pid> | wc -lto see how many FDs the process actually has open- Fix permanently with
/etc/security/limits.conf(PAM-based processes) orLimitNOFILE=(systemd services)
Assumed environment
- OS: Ubuntu / Debian / RHEL family
- Privilege:
sudoavailable - systemd-based service management assumed
What Is "Too many open files"?
A file descriptor (FD) is an integer handle the kernel uses to track open files, sockets, pipes, and other I/O objects. Every time a process opens a file or accepts a connection, it consumes one FD.
Linux enforces two independent limits:
- Per-process limit (EMFILE): how many FDs a single process can hold at once. Checked with
ulimit -n. - System-wide limit (ENFILE): total FDs open across all processes. Checked via
/proc/sys/fs/file-max.
In practice, the error almost always comes from the per-process limit (default: 1024), which is far too low for production web servers, databases, or Node.js apps handling many concurrent connections.
Classic symptoms
- Nginx / Apache / MySQL / Node.js starts throwing errors under load
- Logs contain
Too many open files (EMFILE)oraccept4: Too many open files - Connection count stalls near the value of
ulimit -n(often 1024)
1. Check Current FD Usage
1-1. Check the limit for the current shell
$ ulimit -n # soft limit (effective value) $ ulimit -Hn # hard limit (ceiling a process can raise itself to)
1024 1048576
The soft limit (1024) is the working value. A process can raise it up to the hard limit without special privileges.
1-2. Check a specific process
$ cat /proc/<pid>/limits | grep 'open files'
Limit Soft Limit Hard Limit Units Max open files 65536 65536 files
Count how many FDs the process currently holds:
$ ls /proc/<pid>/fd | wc -l # or $ sudo lsof -p <pid> | wc -l
1-3. Check system-wide FD usage
$ cat /proc/sys/fs/file-nr
13472 0 524288
Three columns: currently allocated / free-but-reserved (always 0) / system ceiling.
Check the ceiling directly:
$ sysctl fs.file-max fs.file-max = 524288
The per-process limit (ulimit -n) runs out long before the system ceiling in nearly every real-world case. Only raise fs.file-max if /proc/sys/fs/file-nr shows the first column approaching the third.
2. Identify the Offending Process
2-1. Rank processes by FD count
$ sudo lsof 2>/dev/null | awk '{print $1, $2}' | sort | uniq -c | sort -rn | head -204821 nginx 1234 3102 mysqld 5678 1204 node 9012
2-2. Inspect what a process has open
$ sudo lsof -p <pid>
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nginx 1234 www 0r REG 8,1 1234 /var/log/nginx/access.log nginx 1234 www 3u IPv4 56789 0t0 TCP *:80 (LISTEN)
A large number of sockets often points to a connection leak — connections accepted but never closed.
2-3. Check socket state
$ ss -s
Total: 12034 TCP: 11820 (estab 8000, closed 200, orphaned 20, timewait 200)
An unusually large estab count suggests the application is not closing connections correctly.
3. Temporary Fix (Immediate Relief)
This changes the limit only for the current shell session. It resets on logout.
$ ulimit -n 65536
To change the limit of an already-running process without restarting it:
$ sudo prlimit --pid <pid> --nofile=65536:65536
ulimit changes are session-scoped. See the next section for permanent configuration.
4. Permanent Configuration
4-1. PAM-based processes (login sessions and conventional daemons)
Add to /etc/security/limits.conf or a file in /etc/security/limits.d/:
$ sudo vi /etc/security/limits.d/99-fd-limits.conf
# * applies to all users; replace with a username for a specific user * soft nofile 65536 * hard nofile 65536 # Specific user example www-data soft nofile 65536 www-data hard nofile 65536
The change takes effect on next login or service restart. Verify:
$ su - www-data -s /bin/bash -c 'ulimit -n' 65536
Ubuntu 18.04+ also lets you set the system-wide default with DefaultLimitNOFILE= in /etc/systemd/system.conf. Because this affects every service, prefer per-service overrides (4-3) unless you need a blanket change.
4-2. Raise the system-wide ceiling (fs.file-max)
Usually unnecessary — fix the per-process limit first. Only do this if file-nr shows the allocated count approaching the ceiling.
$ sudo sysctl -w fs.file-max=1048576 # immediate, resets on reboot
To persist across reboots, create /etc/sysctl.d/99-fd.conf:
$ sudo vi /etc/sysctl.d/99-fd.conf
fs.file-max = 1048576
$ sudo sysctl --system # reload all sysctl.d/*.conf files
4-3. systemd-managed services
systemd does not go through PAM, so limits.conf has no effect. Override per service:
$ sudo systemctl edit nginx # opens an editor for the override
Add and save:
[Service]
LimitNOFILE=65536
Or create the file manually:
$ sudo mkdir -p /etc/systemd/system/nginx.service.d/ $ sudo vi /etc/systemd/system/nginx.service.d/override.conf
[Service]
LimitNOFILE=65536
$ sudo systemctl daemon-reload $ sudo systemctl restart nginx
Verify the limit took effect:
$ cat /proc/$(pgrep -o nginx)/limits | grep 'open files' Max open files 65536 65536 files
LimitNOFILE=infinity is available on kernel 5.15+. On older kernels, specify an explicit number (65536 or 1048576).
5. What Not to Do
- Setting
ulimit -n unlimitedpermanently: if a process leaks FDs due to a bug, it will eventually starve the entire system. Use a reasonable ceiling (65536–1048576). - Raising the limit without investigating the root cause: if the problem is a connection leak (a bug that never closes FDs), raising the limit only delays the crash.
- Expecting
limits.confto affect systemd services: it does not. UseLimitNOFILE=in a systemd unit override. - Setting
fs.file-maxunnecessarily high: the kernel allocates memory per FD; an unconstrained ceiling wastes RAM.