Ulimit

From Segfault
Jump to navigation Jump to search

ulimit(1) is a shell-builtin, its output and values differ across shells and operating system defaults.

Linux

To enable limits, one can just use the ulimit(1) shell-builtin. To enable limits permanently, PAM can be used:

$ grep -r pam_limit /etc/pam.d/
/etc/pam.d/common-session:session  required   pam_limits.so
/etc/pam.d/su:            session  required   pam_limits.so
/etc/pam.d/cron:          session  required   pam_limits.so
/etc/pam.d/login:         session  required   pam_limits.so

Programs like cron or sshd are usually compiled agains libpam.so. For ssh, the sshd_config must set UsePAM=yes.

Use limits.conf to configure reasonable limits. A working example, limiting everybody in the group "users":

root            -       core            1048576         # -c 1024 MB    (0, core file size)
@staff          -       core             524288         # -c  512 MB
*               -       core             524288         # -c  512 MB

*               -       data              32768         # -d   32 MB    (unlimited, data seg size)

@staff          -       fsize         unlimited         # -f            (unlimited, file size)
*               -       fsize           1048576         # -f 1024 MB

*               -       memlock              64         # -l   64 KB    (64 KB, locked memory)

root            -       nofile              512         # -n  512       (1024, open files, max: 2^20)
@staff          -       nofile              256         # -n  256
*               -       nofile              128         # -n  128

*               -       rss              131072         # -m  128 MB    (unlimited, resident set size)
*               -       stack              8192         # -s    8 MB    (8192 KB, stack size)
*               -       cpu           unlimited         # -t            (unlimited, cpu time)

root            -       nproc               512         # -u  512       (1024, number of processes)
@staff          -       nproc               512         # -u  512
*               -       nproc                64         # -u   64

@staff          -       as            unlimited         # -v            (unlimited, per process address space)
*               -       as               524288         # -v  512 MB

*               -       maxlogins            10         #               (unlimited, max number of logins per user)
*               -       maxsyslogins         20         #               (unlimited, max number of logins per system)
*               -       priority              5         # -e    5       (0, priority of user processes)

root            -       locks              1024         # -x 1024       (unlimited, file locks per user)
*               -       locks                32         # -x   32

*               -       sigpending         1024         # -i 1024       (?, pending signals)
*               -       msgqueue           8192         # -q 8192       (819200, POSIX message queues)
*               hard    nice                  0         #               (0, nice level allowed [-20, 19])
*               soft    nice                  5         #
*               -       rtprio                0         # -r    0       (0, realtime priority)

# @users        -       pipe                  8         # -p    8       (8, pipe size in 512 bytes)
# @lusers       -       chroot      /mnt/chroot         # change root to directory (Debian-specific)
  • Group and wildcard limits are not applied to root. To apply a limit to the root user, <domain> must be the literal username root.
  • Notice how we set both soft and hard limits ("-") for most of the settings but a few. For example, we want the "@users" to be reniced to "5" per default but if they need more CPU priority, they can elevate themselves to "0".
  • testparm(1) will complain if nofile is set lower than 2^14:
 $ testparm
 Load smb config files from /etc/samba/smb.conf
 rlimit_max: increasing rlimit_max (512) to minimum Windows limit (16384)
See also Debian #608624 for details on this matter.

Changing ulimit for running processes

To change ulimits for running processes[1][2], the prlimit()[3] syscall is used, available since Linux 2.6.36-rc1[4]

$ prlimit --core -p $$
RESOURCE DESCRIPTION        SOFT      HARD UNITS
CORE     max core file size    0 unlimited blocks

$ prlimit --core=`expr 32 \* 1024 \* 1024`: -p $$             # 32 MB corefile size in bytes
$ prlimit --core -p $$
RESOURCE DESCRIPTION        SOFT      HARD UNITS
CORE     max core file size 33554432 unlimited blocks

$ ulimit -c
32768                                                         # 32 MB corefile size in KBytes

If prlimit is not available[5][6][7], we can still modify the ulimit value of a process via /proc:

$ grep core /proc/$$/limits 
Max core file size        33554432             unlimited            bytes

$ printf "Max core file size=`expr 64 \* 1024 \* 1024`:unlimited" > /proc/$$/limits    # 64 MB corefile size in bytes
$ ulimit -c
65536                                                                                  # 64 MB corefile size in KBytes

Note: For some reason this does not seem to work in more current kernels. Also, only root seems to be allowed to modify these values.

Then there's gdb[2] to change these values, although the interface is a bit cryptic and may not work in all cases:

$ grep RLIMIT_CORE /usr/include/asm-generic/resource.h 
#define RLIMIT_CORE             4       /* max core file size */

$ gdb -p $$
(gdb) set $rlim = &{0ll, 0ll}
(gdb) print getrlimit(4, $rlim)
$1 = 0                                                    # corefile size of 0

(gdb) print *$rlim
$2 = {0, -1}                                              # print softlimit, hardlimit

(gdb) set *$rlim[0] = 64*1024*1024
(gdb) print setrlimit(4, $rlim)
$3 = 0

Solaris

TBD...

MacOS

While ulimit(1) can be used to display and modify current session limits, launchctl(1) will be able to set default values:

$ launchctl limit
       cpu         unlimited      unlimited
       filesize    unlimited      unlimited
       data        unlimited      unlimited
       stack       8388608        67104768
       core        0              unlimited
       rss         unlimited      unlimited
       memlock     unlimited      unlimited
       maxproc     709            1064
       maxfiles    256            unlimited

With launchd.conf(5), these can be set permanently. While /etc/launchd.conf sets the system's default, $HOME/.launchd.conf will set a user's defaults. However, according to the manpage, this is currently unsupported.

$ cat /etc/launchd.conf
#       resource limit  soft            hard 
limit   cpu             unlimited       unlimited
limit   filesize        unlimited       unlimited
limit   data            unlimited       unlimited
limit   stack           8388608         67104768
limit   core            1048576         unlimited
limit   rss             unlimited       unlimited
limit   memlock         unlimited       unlimited
limit   maxproc         709             1064
limit   maxfiles        256             unlimited

Links

References