| |

LFCS 138 ๐Ÿง System Resource Limits โ€” ulimit

โฑ๏ธ Estimated read: 10 min | |

The previous chapters covered disk usage and I/O performance. This chapter covers the limits that constrain how much of those resources a process can consume. The ulimit command is the shell builtin that reads and sets the resource limits for the current shell and the processes it spawns. The LFCS exam tests the distinction between soft and hard limits, the specific flags for the common resources (-n for open files, -u for processes, -s for stack size), and the mechanism for making limits persistent. The critical trap is that ulimit is a per-session setting. A change made with ulimit -n 65535 applies only to the current shell and its children. When the shell exits, the change is gone. The persistent configuration requires /etc/security/limits.conf (for login users) or a systemd unit override (for services).

Key point: The ulimit command sets limits for the current shell. The -H flag sets the hard limit, and the -S flag sets the soft limit. A non-root user can lower the hard limit but cannot raise it. A non-root user can raise the soft limit up to the hard limit. The -a flag shows all current limits. The /etc/security/limits.conf file makes the limits persistent for login sessions via PAM. Systemd services do not read limits.conf and require LimitNOFILE= (or the equivalent) in the unit file.


Why resource limits require a specific mental model

The soft versus hard problem. A soft limit is the current enforcement value. A hard limit is the ceiling that the soft limit cannot exceed. A non-root user can raise the soft limit up to the hard limit, but cannot raise the hard limit. A root user can raise both. The ulimit -Sn shows the soft limit, ulimit -Hn shows the hard limit, and ulimit -n (without a flag) shows the soft limit by default .

The per-session problem. ulimit is a shell builtin. It modifies the limits of the current shell process and the processes it forks. A new shell (a new SSH session, a new terminal) starts with the limits defined in the system configuration. The ulimit command does not modify the system configuration; it modifies the running process. The persistent configuration is the /etc/security/limits.conf file or the systemd unit .

The PAM problem. The /etc/security/limits.conf file is read by the pam_limits module at login. The module sets the limits for the user’s session. If the PAM configuration does not include session required pam_limits.so, the limits.conf file is ignored. On most distributions, this line is included by default in /etc/pam.d/common-session or the equivalent .

The systemd problem. Systemd services do not read /etc/security/limits.conf. A service that needs a higher open-file limit must have the limit set in its unit file with LimitNOFILE=65535 (or the equivalent for other resources). The systemctl edit command creates an override file. The systemctl daemon-reload and systemctl restart commands apply the change .

The trade-off. ulimit is simple for a quick check or a temporary adjustment. The persistent configuration is more complex because it depends on the session type: login users use limits.conf, and services use systemd. The exam tests the ulimit syntax and the distinction between the temporary and persistent configuration.


a. The ulimit syntax and common flags

The ulimit command is a builtin. The -a flag shows all limits. The -H and -S flags select the hard or soft limit. The resource flags select the specific resource.

# Show all limits
ulimit -a

# Show the soft limit for open files
ulimit -Sn

# Show the hard limit for open files
ulimit -Hn

# Set the soft limit for open files
ulimit -n 4096

# Set both soft and hard
ulimit -n 65535

The resource flags are:

FlagResource
-nOpen files
-uMax user processes
-sStack size (KB)
-cCore file size (blocks)
-fFile size (blocks)
-vVirtual memory (KB)
-tCPU time (seconds)

The ulimit -a output shows the resource name, the soft limit, and the unit. The -n is the most commonly tested because the open-file limit is the one that most often causes application failures (e.g., a web server that cannot accept new connections because it has reached the limit) .


b. Making limits persistent with limits.conf

The /etc/security/limits.conf file is the configuration for the pam_limits module. The syntax is <domain> <type> <item> <value>.

# /etc/security/limits.conf
*               soft    nofile          65535
*               hard    nofile          65535
@developers     soft    nproc           4096
@developers     hard    nproc           8192

The <domain> is the user, the group (prefixed with @), or * for all users. The <type> is soft, hard, or - for both. The <item> is the resource name (nofile, nproc, stack, core, etc.). The <value> is the limit .

The limits.conf file is not the only source. The /etc/security/limits.d/ directory contains additional configuration files. The files are read in alphabetical order, and the last matching rule wins. A file in limits.d/ can override a rule in limits.conf .

After modifying limits.conf, the user must log out and log back in for the change to take effect. The su and sudo commands do not re-read the limits unless the PAM configuration is set up to do so. The ulimit -n command in a new session confirms the new value .


c. Systemd services and the LimitNOFILE directive

Systemd services do not read limits.conf. The limits are set in the unit file with the Limit* directives.

# Override for a specific service
sudo systemctl edit nginx

# Add:
[Service]
LimitNOFILE=65535
LimitNPROC=65535

# Apply
sudo systemctl daemon-reload
sudo systemctl restart nginx

The LimitNOFILE directive sets the open-file limit. The LimitNPROC sets the process limit. The LimitCORE sets the core file size. The LimitSTACK sets the stack size. The Limit* directives accept infinity as a value .

The global default for all services is set in /etc/systemd/system.conf with DefaultLimitNOFILE=. The user session default is in /etc/systemd/user.conf with the same directive. The systemctl daemon-reexec command applies the global change without a full reboot .

The cat /proc/<PID>/limits command shows the limits of a running process. This is the verification step: the ulimit in the shell may show one value, but the service process may have a different value because systemd applied the unit file directive .


Complete Example Session

# ============================================
# PART 1: VIEW CURRENT LIMITS
# ============================================

ulimit -a
# Shows all limits for the current shell.
# ============================================
# PART 2: VIEW OPEN FILE LIMITS
# ============================================

ulimit -Sn
# Soft limit: 1024
ulimit -Hn
# Hard limit: 4096
# ============================================
# PART 3: SET A SOFT LIMIT
# ============================================

ulimit -n 2048
ulimit -Sn
# Soft limit: 2048
# ============================================
# PART 4: ATTEMPT TO RAISE THE HARD LIMIT
# ============================================

ulimit -Hn 8192
# Error: cannot raise limit (non-root)
# ============================================
# PART 5: PERSISTENT LIMIT FOR LOGIN USERS
# ============================================

sudo tee -a /etc/security/limits.conf <<'EOF'
* soft nofile 65535
* hard nofile 65535
EOF
# ============================================
# PART 6: VERIFY PAM IS ENABLED
# ============================================

grep pam_limits /etc/pam.d/common-session
# session required pam_limits.so
# ============================================
# PART 7: RE-LOGIN AND VERIFY
# ============================================

# Log out and log back in.
ulimit -n
# 65535
# ============================================
# PART 8: SYSTEMD SERVICE OVERRIDE
# ============================================

sudo systemctl edit nginx
# [Service]
# LimitNOFILE=65535
sudo systemctl daemon-reload
sudo systemctl restart nginx
# ============================================
# PART 9: VERIFY SERVICE LIMITS
# ============================================

cat /proc/$(pgrep nginx | head -1)/limits | grep "open files"
# Max open files 65535

The nine parts trace the resource limits: view, soft/hard check, set soft, attempt hard raise, persistent login limit, PAM check, re-login verification, systemd override, and service verification.


Quick Reference

ulimit Flags

FlagResource
-aAll limits
-HHard limit
-SSoft limit
-nOpen files
-uMax user processes
-sStack size (KB)
-cCore file size (blocks)
-fFile size (blocks)
-vVirtual memory (KB)

limits.conf Syntax

FieldMeaning
<domain>User, @group, or *
<type>soft, hard, or -
<item>Resource name (nofile, nproc)
<value>Limit value

Persistent Configuration

ScopeLocation
Login users/etc/security/limits.conf
Drop-in/etc/security/limits.d/*.conf
Systemd servicesystemctl edit <service>
Systemd global/etc/systemd/system.conf

Systemd Directives

DirectiveResource
LimitNOFILEOpen files
LimitNPROCProcesses
LimitCORECore file size
LimitSTACKStack size

Best Practices

โœ… Do This:

ulimit -a
<!-- Check current limits before changing -->        # โœ…
sudo systemctl edit nginx
<!-- Override limits for a systemd service -->       # โœ…
cat /proc/<PID>/limits
<!-- Verify the process's actual limits -->          # โœ…

โŒ Don’t Do This:

# Assume ulimit changes are persistent
<!-- They apply only to the current shell -->        # โŒ
# Add limits.conf entries for systemd services
<!-- Systemd does not read limits.conf -->           # โŒ
# Set the soft limit above the hard limit
<!-- Not permitted for non-root users -->            # โŒ

Common Pitfalls

PitfallWhy It HappensFix
ulimit change lost after logoutPer-session settingUse limits.conf
limits.conf not appliedPAM not enabled or no re-loginCheck PAM, log out and back in
Systemd service limit ignoredlimits.conf not read by systemdUse LimitNOFILE
Soft limit cannot be raisedHard limit is too lowRaise hard limit as root
Application cannot open filesnofile limit reachedIncrease nofile

Real-World Examples

1. View All Limits

ulimit -a

2. View Soft Limit

ulimit -Sn

3. View Hard Limit

ulimit -Hn

4. Set Soft Limit

ulimit -n 4096

5. Persistent Login Limit

* soft nofile 65535

6. Group Limit

@developers hard nproc 8192

7. Systemd Override

systemctl edit nginx
# LimitNOFILE=65535

8. Systemd Global

DefaultLimitNOFILE=65535

9. Verify Service

cat /proc/<PID>/limits

10. PAM Check

grep pam_limits /etc/pam.d/common-session

Visual

Soft vs Hard Limit

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Hard limit (4096)                           โ”‚
โ”‚  โ””โ”€โ”€ Ceiling for soft limit                  โ”‚
โ”‚                                              โ”‚
โ”‚  Soft limit (1024)                           โ”‚
โ”‚  โ””โ”€โ”€ Current enforcement                     โ”‚
โ”‚                                              โ”‚
โ”‚  Non-root user can raise soft up to hard     โ”‚
โ”‚  Non-root user cannot raise hard             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Persistent Configuration Paths

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Login user                                  โ”‚
โ”‚  โ†’ /etc/security/limits.conf                 โ”‚
โ”‚  โ†’ PAM reads at login                        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Systemd service                             โ”‚
โ”‚  โ†’ systemctl edit <service>                  โ”‚
โ”‚  โ†’ LimitNOFILE=65535                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                   โ”‚
                   โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Verify: cat /proc/<PID>/limits              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Current shell limitsulimit -a
Soft limitulimit -S
Hard limitulimit -H
Open files-n
Max processes-u
Persistent login/etc/security/limits.conf
PAM modulepam_limits.so
Systemd serviceLimitNOFILE=
Verify process/proc/<PID>/limits

Key takeaways:

  • ulimit is a shell builtin. It modifies the limits of the current shell and its children. The change is lost when the shell exits. The persistent configuration is limits.conf for login users and systemd units for services .
  • Soft limits are the enforcement value; hard limits are the ceiling. A non-root user can raise the soft limit up to the hard limit but cannot raise the hard limit. A root user can raise both .
  • limits.conf is read by PAM at login. The pam_limits.so module must be enabled in the PAM configuration. The change takes effect on the next login, not immediately .
  • Systemd services do not read limits.conf. A service that needs a higher limit must have the LimitNOFILE (or equivalent) directive in its unit file, applied with systemctl daemon-reload and systemctl restart .
  • The verification is /proc/<PID>/limits. The ulimit command in the shell shows the shell’s limits. The /proc file shows the actual limits of a specific process, which may differ if systemd applied a directive .

Remember: ulimit is the per-session tool. limits.conf is the login-user persistence. Systemd Limit* directives are the service persistence. The soft limit is the current value. The hard limit is the ceiling. The -a flag shows everything. The -n flag is the open-file limit, which is the one that most often causes application failures.

Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!