ulimit — Set per-process resource limits in bash, zsh, fish, PowerShell, and cmd across all 5 shells
Equivalents in every shell
ulimit -n 8192bash builtin. `-n` open files, `-u` user processes, `-s` stack KB, `-v` virtual memory KB, `-c` core dump KB, `-l` locked memory KB, `-m` resident memory KB (rarely enforced), `-t` CPU seconds. Without value, reads current. `-S` soft (default), `-H` hard (user-lowerable, root-raisable). `-a` summary of all. Effect is per-process and inherited by children.
ulimit -n 8192zsh builtin — same flags as bash, plus zsh-specific `-T` (max number of threads, Linux only). zsh also exposes `limit` (csh-style alternative) with named arguments: `limit descriptors 8192`. Same effect; pick one. `limit -h` shows hard limits.
ulimit -n 8192fish builtin (since fish 2.0). Same flags as bash; `ulimit -a` for summary. Fish lacks the csh-style `limit` command. Per-call overrides for children: `env -i ulimit -n 4096; ./child.sh` (the env-i forces a clean env that inherits the lower limit).
(Get-Process -Id $PID).MaxWorkingSet = 1GBpwsh has no shell-level `ulimit` builtin — Windows resource limits are per-process and live in the Job Object API. `(Get-Process -Id $PID).MaxWorkingSet` adjusts working-set quota. For open-file limits, Windows has no equivalent of `ulimit -n` (handle limits are per-process and tunable via `SetHandleInformation` or by registry — see `HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems\Windows`). On pwsh-Linux, you can shell out to `ulimit` via `bash -c "ulimit -n 8192; pwsh -File ./X.ps1"`.
rem No native equivalentcmd has no `ulimit` builtin and no shell-side equivalent. Windows resource limits are imposed via Job Objects, GPOs (`User Configuration > Administrative Templates > System > Process Quota`), or registry. For per-script soft limits, shell out: `powershell -Command "Set-PSResourceLimit ..."` (community module; no built-in cmdlet ships).
Worked examples
Raise the open-file limit before launching a high-FD server (databases, proxies)
ulimit -n 65536 && ./my-serverulimit -n 65536; ./my-serverShow all current limits (soft) for the current shell
ulimit -aulimit -aGet-Process -Id $PID | Format-List MaxWorkingSet, MinWorkingSet, WorkingSet64Permanently raise open-file limits for a user (Linux — survives reboot)
sudo tee /etc/security/limits.d/my-app.conf <<EOF
my-app soft nofile 65536
my-app hard nofile 65536
EOFGotchas
- `ulimit -n VALUE` only changes the CURRENT shell's limit. Child processes inherit, but anything you launch from a DIFFERENT shell (cron, systemd unit, supervisor) does not get this value. For systemd services, set `LimitNOFILE=65536` in the unit file. For login shells, edit `/etc/security/limits.conf` (PAM-enforced at login).
- Soft (`-S`) limits can be raised back up to the hard (`-H`) limit by any user. Hard limits can only be RAISED by root and can be LOWERED by anyone. Once you lower the hard limit (`ulimit -Hn 4096`), you can't raise it back in that shell session — start a new login session. This is a common footgun in init scripts.
- macOS has additional system-wide limits that override per-process ulimits — `launchctl limit maxfiles` is the macOS equivalent, and it caps what `ulimit -n` can request. Setting `ulimit -n 1000000` on macOS silently caps to `launchctl limit maxfiles` (default 524288 on macOS 14+).
- pwsh on Windows has NO equivalent of Linux's `ulimit -n` — Windows handle limits are per-process at ~16M handles and not user-tunable from the shell. If you need handle accounting on Windows, profile with `handle.exe` (SysInternals) instead of trying to raise a limit.
- cmd users sometimes hit the **8191-char command-line limit** (an undocumented `lpCommandLine` cap in `CreateProcess`). It's NOT a ulimit — it's a hard Windows OS limit. The workaround is response files (`@args.txt`) or stuffing the args through `cmd /c file.bat` with the bat file reading from disk.