opscape

Shell builtins · bash builtin

ulimit

Show or set per-process resource limits such as open files, core size and stack size.

ulimit [-HS] [-a | -n | -c | -f | -s | -u | -v | -t ...] [LIMIT]

10 of 10 examples run in Debian 13.7 on 2026-10-31 · manual: bash(1)

ulimit is a shell builtin that reads and changes the resource limits of the shell, which every command started from it inherits. The one people meet most is -n, the maximum number of open files (and sockets) per process: the "Too many open files" error from a busy server or a big build is that limit being hit. Others cap core dump size (-c), file size (-f), stack size (-s), CPU seconds (-t) and the number of processes (-u).

Each limit has two values. The soft limit is what is enforced; the hard limit is the ceiling the soft limit may be raised to. Any user can lower either or raise the soft limit up to the hard one; only root can raise a hard limit, and lowering it is a one-way trip for that shell. Without -S or -H, ulimit shows the soft value and sets both.

It has to be a builtin: a separate program could only change its own limits, which would vanish when it exited. Changes last for the current shell and its children, so the usual pattern is to run ulimit in a subshell or at the top of a wrapper script. Permanent, system-wide limits live in /etc/security/limits.conf (for login sessions) or in a systemd unit's LimitNOFILE= and friends (for services).

Examples

Show the open-files limit

ulimit -n
explain
output
1024

1024 is the soft limit most Linux systems start with. A process that tries to open file number 1025 gets EMFILE, "Too many open files".

Show the soft and hard limits separately

echo "soft: $(ulimit -Sn)  hard: $(ulimit -Hn)"
explain
output
soft: 1024  hard: 524288

The hard limit here is 524288, so this user can raise the soft limit a long way without root.

List every limit

ulimit -a | head -n 12
explain
output
real-time non-blocking time  (microseconds, -R) unlimited
core file size              (blocks, -c) unlimited
data seg size               (kbytes, -d) unlimited
scheduling priority                 (-e) 0
file size                   (blocks, -f) unlimited
pending signals                     (-i) 1029519
max locked memory           (kbytes, -l) 8192
max memory size             (kbytes, -m) unlimited
open files                          (-n) 1024
pipe size                (512 bytes, -p) 8
POSIX message queues         (bytes, -q) 819200
real-time priority                  (-r) 0

-a prints each limit with its unit and the option letter that changes it. Trimmed to the first twelve lines with head here.

Raise the open-files limit for one command

(ulimit -n 4096; echo "inside: $(ulimit -n)")
echo "outside: $(ulimit -n)"
output
inside: 4096
outside: 1024

The parentheses run a subshell, so the raised limit applies only there and to anything it starts. The parent shell keeps 1024. Wrapping a server's start command like this is a common quick fix.

Try to go above the hard limit

ulimit -n $(( $(ulimit -Hn) + 1 ))
explain
outputexit 1
/bin/bash: line 1: ulimit: open files: cannot modify limit: Operation not permitted

Raising past the hard limit needs root, so a normal user gets Operation not permitted and status 1.

Lower a hard limit and find you cannot undo it

ulimit -Hn 2048
echo "hard now: $(ulimit -Hn)"
ulimit -Hn 4096
outputexit 1
hard now: 2048
/bin/bash: line 3: ulimit: open files: cannot modify limit: Operation not permitted

Lowering a hard limit is allowed, raising it back is not, even for the same user in the same shell. Only a new session (or root) gets the old ceiling back.

Check and disable core dumps

echo "core limit: $(ulimit -c)"
ulimit -c 0
echo "core limit now: $(ulimit -c)"
output
core limit: unlimited
core limit now: 0

A limit of unlimited allows full core dumps when a program crashes; 0 disables them. Many distributions default to 0 for login shells, and debugging a crash starts with ulimit -c unlimited. Where the core goes is decided separately by the kernel's core_pattern.

Cap the size of files a command can write

(ulimit -f 1; head -c 10000 /dev/zero > big.bin)
echo "status: $?"
ls -l big.bin
output
/bin/bash: line 1:  3702 File size limit exceeded(core dumped) head -c 10000 /dev/zero > big.bin
status: 153
-rw-r--r-- 1 dev dev 1024 Oct 31 20:21 big.bin

-f counts in 1024-byte blocks, so the limit is 1 KiB. The write past it raises SIGXFSZ, which kills head; bash reports the signal and the status is 128 + 25 = 153. Core dumps are allowed in this sandbox, hence (core dumped). The file stops at exactly 1024 bytes.

Show the stack size limit

ulimit -s
ulimit -Hs
output
8192
unlimited

The soft stack limit is 8192 KiB (8 MiB), the usual Linux default. Deeply recursive programs that crash with a segmentation fault sometimes need it raised.

Inspect the limits of a running process

prlimit --pid $$ --nofile --core
explain
output
RESOURCE DESCRIPTION                   SOFT      HARD UNITS
NOFILE   max number of open files      1024    524288 files
CORE     max core file size       unlimited unlimited bytes

ulimit only sees the current shell. util-linux prlimit reads (and, with permission, changes) the limits of any process by PID; $$ here is the shell itself. For a quick look, cat /proc/PID/limits shows the same table.

Common pitfalls

  • Raising ulimit -n in your shell and expecting a running service to pick it up. Limits are inherited at process start; restart the service, and for systemd services set LimitNOFILE= in the unit, since /etc/security/limits.conf does not apply to them.

  • Running ulimit -n 65535 in a script that is executed (not sourced) and then checking the limit in your terminal. The change died with the script's shell.

  • Setting a limit without -S and locking yourself out of raising it again: plain ulimit -n 2048 sets the hard limit too. Use ulimit -Sn when you only want to adjust the soft value.

  • Reading -f, -c and -s values as bytes. Bash counts them in 1024-byte blocks or kibibytes (512-byte blocks for -p); ulimit -a shows each unit.

GNU vs BSD and macOS

The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).

  • ulimit is a shell builtin, so its options depend on the shell rather than the OS. POSIX only requires -f; bash and zsh support the full set on both Linux and macOS, while dash (/bin/sh on Debian) supports fewer letters.

  • macOS has historically given shells a low soft open-files limit (256) and enforces a separate system-wide cap, shown by launchctl limit maxfiles; check ulimit -n there before assuming Linux defaults.

Options worth knowing

A selection, described in our own words. For the full list, see bash(1).

OptionWhat it does
-SUse the soft limit.
-HUse the hard limit.
-aShow all current limits.
-n NMaximum number of open file descriptors.
-c NMaximum core dump size, in 1024-byte blocks.
-f NMaximum size of files written, in 1024-byte blocks.
-s NMaximum stack size, in kibibytes.
-u NMaximum number of processes for the user.
-v NMaximum virtual memory, in kibibytes.
-t NMaximum CPU time, in seconds.
-l NMaximum locked-in-memory size, in kibibytes.
-d NMaximum data segment size, in kibibytes.
-m NMaximum resident set size (not enforced by modern Linux).
-i NMaximum number of pending signals.
-q NMaximum bytes in POSIX message queues.
-e NMaximum scheduling priority (nice) value.
-r NMaximum real-time scheduling priority.
-x NMaximum number of file locks.
-pShow the pipe buffer size, in 512-byte blocks (read-only).

Related