ulimit Command in Linux: Check and Set Resource Limits

Deepak Prasad
Tested on Red Hat Enterprise Linux 10.2 (lab VM)
Package bash 5.2.26
pam 1.6.1 (pam_limits)
util-linux 2.40.2 (prlimit)
Applies to RHEL, Rocky Linux, AlmaLinux, Fedora, Debian, Ubuntu, and other GNU/Linux systems with Bash and PAM
Privilege Normal user for checks and soft-limit changes within hard limits; root or sudo for limits.d, hard-limit raises, and systemd units
Scope Check shell limits with ulimit, raise open-file limits temporarily, persist login limits in limits.d, set systemd LimitNOFILE, and inspect limits on running processes with /proc and prlimit
Related guides systemctl command
su command
nice and renice
SSH command
chgrp command

ulimit is a shell builtin that shows or changes resource limits for the current shell and the processes it starts. Limits apply to processes and are inherited by child processes — they are not global kernel tunables. Use ulimit for quick checks and temporary changes in an interactive session; use /etc/security/limits.d/ for persistent login limits and systemd Limit* directives for services.


Quick reference: ulimit commands

Task Command
All limits (current shell) ulimit -a
Soft limits only ulimit -Sa
Hard limits only ulimit -Ha
Open files (effective) ulimit -n
Open files soft / hard ulimit -Sn / ulimit -Hn
Max user processes ulimit -u
Stack size (KB) ulimit -s
Raise open files (session) ulimit -Sn 4096
Limits on a PID prlimit --pid PID --nofile
Service file limit systemctl show unit -p LimitNOFILE

1. What does ulimit do in Linux?

Linux tracks per-process limits such as open file descriptors, stack size, and maximum user processes. The ulimit command is implemented as a shell builtin in Bash (and similar shells), not as a separate binary. It adjusts limits for the current shell session; child commands and scripts started from that shell inherit those values.

ulimit is the right tool when you are debugging an interactive login, an SSH session, or a script run from your shell. It does not change limits for an already-running daemon started by systemd, and it does not replace /etc/security/limits.d/ for permanent per-user login policy.


2. Check current ulimit values

List every limit for the current shell:

bash
ulimit -a
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) 22995
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
stack size                  (kbytes, -s) 8192
cpu time                   (seconds, -t) unlimited
max user processes                  (-u) 22995
virtual memory              (kbytes, -v) unlimited
file locks                          (-x) unlimited

The open files line (-n) is the limit most often hit on busy servers. Values vary by distribution, PAM defaults, and whether you are root or a normal user.

Query individual limits when you already know which one matters:

bash
ulimit -n
output
1024

Max user processes (-u):

bash
ulimit -u
output
22995

Stack size in kilobytes (-s):

bash
ulimit -s
output
8192

Core dump size (-c):

bash
ulimit -c
output
unlimited

Locked memory in kilobytes (-l):

bash
ulimit -l
output
8192
Option Limit Typical use
-n Open file descriptors Web servers, databases, many connections
-u Max user processes Fork-heavy apps, thread pools
-s Stack size (KB) Deep recursion, some runtimes
-c Core file size Crash dumps
-l Locked memory (KB) Databases, RDMA, mlock

Run ulimit --help in Bash for the full option list; this guide focuses on the limits administrators change most often.


3. Soft vs hard ulimit

Each resource has two ceilings:

  • Soft limit — enforced now for the process
  • Hard limit — ceiling for the soft limit. An unprivileged process can lower its hard limit but cannot raise it again; raising it requires sufficient privilege

Read both for open files:

bash
ulimit -Sn
output
1024

The hard ceiling for the same resource:

bash
ulimit -Hn
output
524288

A normal user can raise the soft open-file limit up to the hard limit for the current shell session:

bash
ulimit -Sn 4096

Confirm the new effective value:

bash
ulimit -n
output
4096

You cannot set soft above hard, and a non-root user cannot raise the hard limit with ulimit:

bash
ulimit -Hn 20000
output
-bash: ulimit: open files: cannot modify limit: Operation not permitted

Persistent hard limits for login sessions can be supplied through pam_limits; systemd services use their own Limit* settings. The rule in one line: soft limit ≤ hard limit.


4. Fix "Too many open files" with ulimit -n

Open-file exhaustion (Too many open files) is the most common production ulimit problem. Inspect soft and hard before you change anything:

bash
ulimit -Sn
output
1024

Read the hard open-files ceiling:

bash
ulimit -Hn
output
524288

Raise the soft limit for this shell session only:

bash
ulimit -Sn 65535

Confirm the effective value:

bash
ulimit -n
output
65535

This lasts until the shell exits. Set the higher limit in the same shell before starting a long-running program; the child process inherits that resource limit.

If 65535 exceeds your hard limit, lower the target or raise the hard limit through limits.d or systemd instead.


5. Set ulimit permanently with limits.conf / limits.d

Session ulimit changes disappear when you log out. For login users, rules in /etc/security/limits.conf and /etc/security/limits.d/*.conf are applied only when the relevant PAM session stack includes pam_limits.so.

Prefer a drop-in file under limits.d rather than editing limits.conf directly:

text
/etc/security/limits.d/90-app-limits.conf
appuser soft nofile 65535
appuser hard nofile 65535
appuser soft nproc 4096
appuser hard nproc 4096

Apply the same limits to every member of a group with @:

text
@developers soft nofile 65535
@developers hard nofile 65535

After you add or edit a file, start a new login session — open a fresh SSH connection or su - username — then verify:

bash
ulimit -Sn
output
65535

Hard limit from the same limits.d entry:

bash
ulimit -Hn
output
65535

A reboot is not required. Limits attach when PAM opens the session (with pam_limits in the stack), not when the file is saved.

On Linux 2.4.30 and later, the legacy rss (maximum resident set size) limit in limits.conf is ignored — do not rely on rss entries for modern kernels.


6. Why limits.conf does not change a systemd service

limits.d affects PAM login sessions (SSH, console login, su -) when pam_limits.so runs. systemd-managed service processes do not normally obtain their resource limits from PAM limits.conf / limits.d; configure the service with systemd Limit* directives instead.

text
/etc/security/limits.d/*.conf  →  PAM login session  →  user shell

systemd unit file            →  systemd exec       →  daemon process

For a service such as nginx or sshd, set limits in the unit or a drop-in:

bash
sudo systemctl edit nginx.service
ini
[Service]
LimitNOFILE=65535

Reload systemd and restart the service after you save the drop-in. Inspect what systemd applied:

bash
systemctl show sshd -p LimitNOFILE
output
LimitNOFILE=524288

Related directives on the [Service] section include LimitNOFILE, LimitNPROC, LimitCORE, and LimitMEMLOCK. LimitNPROC= is counted by real UID and can affect multiple processes for the same user; use TasksMax= when you need a service-scoped task limit. See systemd.exec(5) for the full list; this guide does not replace a systemd resource-tuning chapter.


7. Check resource limits for a running process

ulimit in your shell describes your shell, not necessarily a background daemon started earlier by systemd.

Read limits from the kernel for a specific PID:

bash
cat /proc/$$/limits
output
Limit                     Soft Limit           Hard Limit           Units
Max cpu time              unlimited            unlimited            seconds
Max file size             unlimited            unlimited            bytes
Max data size             unlimited            unlimited            bytes
Max stack size            8388608              unlimited            bytes
Max core file size        unlimited            unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             22995                22995                processes
Max open files            524288               524288               files
Max locked memory         8388608              8388608              bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks

$$ is the current shell PID. Replace it with the application PID when you troubleshoot a service.

prlimit from util-linux prints the same data in a compact form:

bash
prlimit --pid $$ --nofile
output
RESOURCE DESCRIPTION                SOFT   HARD UNITS
NOFILE   max number of open files 524288 524288 files

Compare shell ulimit -n with prlimit on the service PID when logs still report too many open files — the daemon often has a different limit than your interactive session.


8. Common ulimit errors and problems

Problem Check
ulimit -n change fails Compare soft to hard with ulimit -Sn and ulimit -Hn; soft cannot exceed hard
Operation not permitted on ulimit -H Normal users cannot raise hard limits — use limits.d or systemd
limits.conf change not visible Open a new login session; confirm pam_limits.so is in the session PAM stack
limits.conf does not affect a service systemd-managed processes use unit LimitNOFILE= (not PAM limits.d)
Application still reports too many open files Inspect cat /proc/PID/limits or prlimit --pid PID --nofile
ulimit differs between users Compare /etc/security/limits.d/ entries and group rules (@group)
Shell limit differs from service Login PAM path vs systemd Limit* — they are separate mechanisms

Summary

Use ulimit -a and ulimit -n to see what your shell enforces today. Soft limits are the active ceiling; hard limits are the ceiling for soft limits. An unprivileged process may lower its hard limit but cannot raise it again; raising a hard limit requires sufficient privilege. For the common open-files case, ulimit -Sn followed by verification with ulimit -n fixes a session temporarily; /etc/security/limits.d/ makes per-user or per-group limits persist across logins when pam_limits.so runs in the session stack.

systemd-managed service processes do not normally obtain limits from PAM limits.conf / limits.d — set LimitNOFILE and related directives on the unit, then confirm with systemctl show. When logs still disagree with your shell, check the real process with /proc/PID/limits or prlimit. For service management context, see systemctl command.


References


Frequently Asked Questions

1. What is the difference between soft and hard ulimit?

The soft limit is what the kernel enforces for the process now. The hard limit is the ceiling for the soft limit; an unprivileged process can lower its hard limit but cannot raise it again without sufficient privilege. Use ulimit -Sn and ulimit -Hn to read both for open files.

2. Why does limits.conf not affect my systemd service?

systemd-managed service processes do not normally obtain resource limits from PAM limits.conf or limits.d. Set LimitNOFILE or related Limit directives in the service unit or drop-in, then verify with systemctl show.

3. How do I check ulimit for a running process?

Read cat /proc/PID/limits or run prlimit --pid PID --nofile. Shell ulimit shows the interactive session limits, which may differ from a service started by systemd.

4. Why does ulimit say cannot modify limit Operation not permitted?

A normal user cannot raise the hard limit or set soft above hard. Check ulimit -Hn, use limits.d for persistent raises at login, or use root or systemd unit limits for services.
Omer Cakmak

Linux Administrator

Highly skilled at managing Debian, Ubuntu, CentOS, Oracle Linux, and Red Hat servers. Proficient in bash scripting, Ansible, and AWX central server management, he handles server operations on OpenStack, KVM, Proxmox, and VMware.

  • Debian
  • Ubuntu
  • Linux
  • Red Hat Enterprise Linux
  • Shell Script
  • System Administration