The kernel limits every process: how many files it keeps open, how many
processes its user starts, how big a core file it writes on a crash. Limits
are inherited: a child gets its parent's limits. The open files limit is the
one people hit most. A connection socket is an open file too: a server with
a thousand clients holds a thousand descriptors.
Soft and hard
Every limit has two values. The soft one is in effect now. The hard one is
the ceiling up to which a process raises its soft limit by itself. Both can
be lowered; only root raises the hard one, and not above fs.nr_open
(1048576 on the training machine).
student@ubuntu:~$ ulimit -Sn; ulimit -Hn
1024
1048576
student@ubuntu:~$ ulimit -n 4096; ulimit -Sn; ulimit -Hn
4096
4096
student@ubuntu:~$ ulimit -Hn 8192
-bash: ulimit: open files: cannot modify limit: Operation not permitted
ulimit -n without -S or -H in bash changes both values at once. The
hard limit dropped to 4096, and student can no longer raise it in this
shell. The soft one alone is ulimit -Sn 2048.
Kinds of limits
ulimit |
limits.conf |
systemd |
What |
On the machine |
-n |
nofile |
LimitNOFILE |
open files and sockets |
1024 |
-u |
nproc |
LimitNPROC |
processes of the user |
1679 |
-c |
core |
LimitCORE |
core file size |
0 |
-s |
stack |
LimitSTACK |
stack, KiB |
8192 |
-l |
memlock |
LimitMEMLOCK |
locked memory, KiB |
65536 |
-f |
fsize |
LimitFSIZE |
file size |
unlimited |
The "On the machine" column holds student's soft values from ulimit -a.
Process limits: /proc/<PID>/limits
ulimit shows the limits of your shell. The limits of another process are
in /proc/<PID>/limits, which any user can read. For the ssh service:
| Limit |
Soft Limit |
Hard Limit |
Units |
| Max open files |
1024 |
524288 |
files |
prlimit changes the limits of a running process without a restart:
student@ubuntu:~$ s=$(systemctl show -p MainPID --value ssh)
student@ubuntu:~$ sudo prlimit --pid $s --nofile
RESOURCE DESCRIPTION SOFT HARD UNITS
NOFILE max number of open files 1024 524288 files
student@ubuntu:~$ sudo prlimit --pid $s --nofile=4096:8192
This lasts until the process restarts. A permanent value for a service goes
into its unit.
A service limit: LimitNOFILE
systemd services get their limits from systemd: ulimit in a terminal and
/etc/security/limits.conf do not affect them. The default is soft 1024,
hard 524288:
systemctl show -p DefaultLimitNOFILE -p DefaultLimitNOFILESoft
DefaultLimitNOFILE=524288
DefaultLimitNOFILESoft=1024
Your own limit goes into a drop-in:
sudo mkdir -p /etc/systemd/system/ssh.service.d
printf '[Service]\nLimitNOFILE=65536\n' \
| sudo tee /etc/systemd/system/ssh.service.d/limits.conf
sudo systemctl daemon-reload
sudo systemctl restart ssh
grep 'open files' /proc/$(systemctl show -p MainPID --value ssh)/limits
LimitNOFILE=65536 sets both values; different ones are
LimitNOFILE=4096:65536 (soft:hard). After daemon-reload, systemctl show
already prints 65536, while the running process keeps the old limits until
a restart:
| Moment |
systemctl show |
/proc/<PID>/limits |
after daemon-reload |
65536 |
old values |
after restart |
65536 |
65536 and 65536 |
limits.conf: limits at login
/etc/security/limits.conf and the files /etc/security/limits.d/*.conf
are read by a PAM module at login — ssh, login, su -l. That is how
user sessions get their limits. On the training machine the file holds only
comments.
deploy soft nofile 65535
deploy hard nofile 65535