Situatie
On Linux computers, system resources are shared amongst the users. Try to use more than your fair share and you’ll hit an upper limit. You might also bottleneck other users or processes.
Solutie
The system-wide maximum number of file handles can be seen with this command.
cat /proc/sys/fs/file-max
This returns a preposterously large number of 9.2 quintillion. That’s the theoretical system maximum. It’s the largest possible value you can hold in a 64-bit signed integer. Whether your poor computer could actually cope with that many files open at once is another matter altogether.
At the user level, there isn’t an explicit value for the maximum number of open files you can have. But we can roughly work it out. To find out the maximum number of files that one of your processes can open, we can use the ulimit
command with the -n
(open files) option.
ulimit -n
And to find the maximum number of processes a user can have we’ll use ulimit
with the -u
(user processes) option.
ulimit -u
Multiplying 1024 and 7640 gives us 7,823,360. Of course, many of those processes will be already used by your desktop environment and other background processes. So that’s another theoretical maximum, and one you’ll never realistically achieve.
The important figure is the number of files a process can open. By default, this is 1024. It’s worth noting that opening the same file 1024 times concurrently is the same as opening 1024 different files concurrently. Once you’ve used up all of your file handles, you’re done.
It’s possible to adjust the number of files a process can open. There are actually two values to consider when you’re adjusting this number. One is the value it is currently set to, or that you’re trying to set it to. This is called the soft limit. There’s a hard limit too, and this is the highest value that you can raise the soft limit to.
The way to think about this is the soft limit really is the “current value” and the upper limit is the highest value the current value can reach. A regular, non-root, user can raise their soft limit to any value up to their hard limit. The root user can increase their hard limit.
To see the current soft and hard limits, use ulimit
with the -S
(soft) and -H
(hard) options, and the -n
(open files) option.
ulimit -Sn
ulimit -Hn
To create a situation where we can see the soft limit being enforced, we created a program that repeatedly opens files until it fails. It then waits for a keystroke before relinquishing all the file handles it used. The program is called open-files
.
./open-Files
It opens 1021 files and fails as it tries to open file 1022.
1024 minus 1021 is 3. What happened to the other three file handles? They were used for the STDIN
, STDOUT
, and STDERR
streams. They’re created automatically for each process. These always have file descriptor values of 0, 1, and 2.
We can see these using the lsof
command with the -p
(process) option and the process ID of the open-files
program. Handily, it prints its process ID to the terminal window.
lsof -p 11038
Of course, In a real-world situation, you might not know which process has just gobbled up all the file handles. To start your investigation you could use this sequence of piped commands. It’ll tell you the fifteen most prolific users of file handles on your computer.
lsof | awk '{ print $1 " " $2; }' | sort -rn | uniq -c | sort -rn | head -15
To see more or fewer entries adjust the -15
parameter to the head
command. Once you’ve identified the process, you need to figure out whether it has gone rogue and is opening too many files because it is out of control, or whether it really needs those files. If it does need them, you need to increase its file handle limit.
Increasing the Soft Limit
If we increase the soft limit and run our program again, we should see it open more files. We’ll use the ulimit
command and the -n
(open files) option with a numeric value of 2048. This will be the new soft limit.
ulimit -n 2048
This time we successfully opened 2045 files. As expected, this is three less than 2048, because of the file handles used for STDIN
, STDOUT
, and STDERR
.
Making Permanent Changes
Increasing the soft limit only affects the current shell. Open a new terminal window and check the soft limit. You’ll see it is the old default value. But there is a way to globally set a new default value for the maximum number of open files a process can have that is persistent and survives reboots.
Out-dated advice often recommends you edit files such as “/etc/sysctl.conf” and “/etc/security/limits.conf.” However, on systemd-based distributions, these edits don’t work consistently, especially for graphical log-in sessions.
The technique shown here is the way to do this on systemd-based distributions. There are two files we need to work with. The first is the “/etc/systemd/system.conf” file. We’ll need to use sudo
.
sudo gedit /etc/systemd/system.conf
Search for the line that contains the string “DefaultLimitNOFILE.” Remove the hash “#” from the start of the line, and edit the first number to whatever you want your new soft limit for processes to be. We chose 4096. The second number on that line is the hard limit. We didn’t adjust this.
Save the file and close the editor. We need to repeat that operation on the “/etc/systemd/user.conf” file.
sudo gedit /etc/systemd/user.conf
Make the same adjustments to the line containing the string “DefaultLimitNOFILE.”
Save the file and close the editor. You must either reboot your computer or use the systemctl
command with the daemon-reexec
option so that systemd
is re-executed and ingests the new settings.
sudo systemctl daemon-reexec
Opening a terminal window and checking the new limit should show the new value you set. In our case that was 4096.
ulimit -n
We can test this is a live, operational value by rerunning our file-greedy program.
./open-Files
The program fails to open file number 4094, meaning 4093 were files opened. That’s our expected value, 3 less than 4096.
Leave A Comment?