January 16, 2013

A bashism a week: ulimit

Setting resource limits from a shell script is commonly done with the ulimit command.
Shells provide it as a built-in, if they provide it at all. As far as I know, there is no non-built-in ulimit command. One could be implemented with the Linux-specific prlimit system call, but even that requires a fairly "recent" kernel version (circa 2010).

Depending on the kind of resource you want to limit, you may get away with what some shells such as dash provide: CPU, FSIZE, DATA, STACK, CORE, RSS, MEMLOCK, NPROC, NOFILE, AS, LOCKS. I.e. options tfdscmlpnvw, plus H for the hard limit, S for the soft limit, and a for all. Bash allows other resources to be limited.

Remember, if you rely on any non-standard behaviour or feature make sure you document it and, if feasible, check for it at run-time. ulimit is not required by POSIX:2001 to be implemented for the shell.


  1. In fact, even the standard limits, and sometimes their letters, are dependent on the shell *and* the operating system.

    Usually, -d for datasize and -n for nfds is pretty safe, but on Debian GNU/Linux systems with /bin/sh → mksh-static, there is no ulimit due to klibc limitations (GNU/Hurd and GNU/kFreeBSD build statically against eglibc, which is definitely more yucky but leaves them with one).

    Some OSes do not support limits at all, or don’t even support those standard limits.

    Use code like this:

    if (ulimit -d) >/dev/null 2>&1; then
    ulimit -dS $(ulimit -dH)

    This “unlimits” the datasize if the shell supports it. (There’s no way to know that -d is really datasize, but -d is about the most universal one.) The parenthes─ôs are necessary.

  2. I should probably mention that util-linux 2.21 and greater provide a prlimit command that can be used instead of ulimit on Linux systems.
    I'm glad that its interface is not compatible with ulimit's.