ulimitShow and set per-process resource limits
ulimit shows and changes the resource limits of your shell and everything it starts: open files, processes, core file size, stack size and more. 'Too many open files' errors, missing core dumps and fork failures usually come down to one of these limits.
ulimit [-S|-H] [-a | -n | -u | -c | -s | -v | -l ...] [LIMIT]You want to see the limits your shell, and anything you start from it, are running with.
ulimitA shell builtin (not a program): it changes the limits of the current shell process itself.
Every process has a set of resource limits (rlimits) stored in the kernel, each with a soft and a hard value. The kernel enforces the soft one: an open() beyond RLIMIT_NOFILE fails with EMFILE, a fork() beyond RLIMIT_NPROC fails with EAGAIN, a core dump is cut at RLIMIT_CORE. Any process can lower its limits or raise the soft value up to the hard value; raising the hard value needs root (CAP_SYS_RESOURCE). ulimit is built into the shell because it must call setrlimit() on the shell's own process; children inherit the limits through fork and exec. That is why the starting point matters: on login, PAM's pam_limits module applies /etc/security/limits.conf to SSH and console sessions, but services started by systemd never go through PAM. They get LimitNOFILE= and friends from their unit file, or systemd's defaults (DefaultLimitNOFILE=1024:524288). The real limits of any running process are in /proc/PID/limits, and prlimit can change them without a restart.
Login sessions get limits from PAM's limits.conf; systemd services get them from their unit. Children inherit, and the kernel enforces.
When you SSH in, sshd runs the PAM session stack. pam_limits reads /etc/security/limits.conf and limits.d and calls setrlimit before your shell starts.
-aShow all limits with their units-nOpen file descriptors (files, sockets, pipes)-uProcesses/threads per user (fork bomb protection)-cCore file size in blocks (0 = no core dumps)-sStack size in KB (default 8192)-v / -mVirtual memory / resident set size (RSS limit isn't enforced on Linux)-lLocked memory (mlock), matters for databases and eBPF-S / -HSoft (enforced) / hard (ceiling); default sets both/proc/PID/limitsThe limits a running process really hasLimitNOFILE=systemd unit setting; limits.conf does not apply to servicesAdding nofile to /etc/security/limits.conf for a systemd servicelimits.conf is applied by PAM at login; systemd services don't log in, so it has no effect on them.
LimitNOFILE=65535 in the unit (systemctl edit SERVICE), then restartRunning ulimit -n 65535 in one terminal and restarting the service from anotherulimit changes only the current shell and its future children; services and other sessions are untouched.
Set the limit where the process is started (unit file, Docker --ulimit, Kubernetes node config)ulimit -c 0 (or -n 1024) to change a limit 'temporarily'Without -S, bash lowers the hard limit too, and a normal user can never raise it back in that session.
ulimit -S -c 0Checking your own shell's ulimit -n to debug a service's EMFILEYour shell's limits say nothing about another process's.
cat /proc/$(pgrep -f NAME)/limits, or prlimit --pid PIDTry these on a Linux machine of your own. Each task has a hint and a solution.
Print your soft and hard limits for open files.
Raise the soft open-files limit to 4096 in a subshell only, and prove the parent shell is unchanged.
Find the open-files limit of the running sshd process (or any root daemon).
ulimitShow and set per-process resource limits
ulimit shows and changes the resource limits of your shell and everything it starts: open files, processes, core file size, stack size and more. 'Too many open files' errors, missing core dumps and fork failures usually come down to one of these limits.
ulimit [-S|-H] [-a | -n | -u | -c | -s | -v | -l ...] [LIMIT]You want to see the limits your shell, and anything you start from it, are running with.
ulimitA shell builtin (not a program): it changes the limits of the current shell process itself.
Every process has a set of resource limits (rlimits) stored in the kernel, each with a soft and a hard value. The kernel enforces the soft one: an open() beyond RLIMIT_NOFILE fails with EMFILE, a fork() beyond RLIMIT_NPROC fails with EAGAIN, a core dump is cut at RLIMIT_CORE. Any process can lower its limits or raise the soft value up to the hard value; raising the hard value needs root (CAP_SYS_RESOURCE). ulimit is built into the shell because it must call setrlimit() on the shell's own process; children inherit the limits through fork and exec. That is why the starting point matters: on login, PAM's pam_limits module applies /etc/security/limits.conf to SSH and console sessions, but services started by systemd never go through PAM. They get LimitNOFILE= and friends from their unit file, or systemd's defaults (DefaultLimitNOFILE=1024:524288). The real limits of any running process are in /proc/PID/limits, and prlimit can change them without a restart.
Login sessions get limits from PAM's limits.conf; systemd services get them from their unit. Children inherit, and the kernel enforces.
When you SSH in, sshd runs the PAM session stack. pam_limits reads /etc/security/limits.conf and limits.d and calls setrlimit before your shell starts.
-aShow all limits with their units-nOpen file descriptors (files, sockets, pipes)-uProcesses/threads per user (fork bomb protection)-cCore file size in blocks (0 = no core dumps)-sStack size in KB (default 8192)-v / -mVirtual memory / resident set size (RSS limit isn't enforced on Linux)-lLocked memory (mlock), matters for databases and eBPF-S / -HSoft (enforced) / hard (ceiling); default sets both/proc/PID/limitsThe limits a running process really hasLimitNOFILE=systemd unit setting; limits.conf does not apply to servicesAdding nofile to /etc/security/limits.conf for a systemd servicelimits.conf is applied by PAM at login; systemd services don't log in, so it has no effect on them.
LimitNOFILE=65535 in the unit (systemctl edit SERVICE), then restartRunning ulimit -n 65535 in one terminal and restarting the service from anotherulimit changes only the current shell and its future children; services and other sessions are untouched.
Set the limit where the process is started (unit file, Docker --ulimit, Kubernetes node config)ulimit -c 0 (or -n 1024) to change a limit 'temporarily'Without -S, bash lowers the hard limit too, and a normal user can never raise it back in that session.
ulimit -S -c 0Checking your own shell's ulimit -n to debug a service's EMFILEYour shell's limits say nothing about another process's.
cat /proc/$(pgrep -f NAME)/limits, or prlimit --pid PIDTry these on a Linux machine of your own. Each task has a hint and a solution.
Print your soft and hard limits for open files.
Raise the soft open-files limit to 4096 in a subshell only, and prove the parent shell is unchanged.
Find the open-files limit of the running sshd process (or any root daemon).