Linux ulimit详解

ulimit 用于限制 shell 启动的进程所占用的资源,支持以下各种类型的限制:所创建的内核文件的大小、进程数据块的大小、Shell 进程创建文件的大小、内存锁住的大小、常驻内存集的大小、打开文件描述符的数量、分配堆栈的最大大小、CPU 时间、单个用户的最大线程数、Shell 进程所能使用的最大虚拟内存。

ulimit 命令

ulimit 有软限制和硬限制之分:

  • 软限制:任何进程都可以修改软限制,但是软限制不能超过硬限制;
  • 硬限制:普通进程可以降低硬限制,只有 root 进程可以提高硬限制;

软限制是内核对相应资源强制执行的值,硬限制是软限制的上限:非特权进程可以将其软限制设置为 0 到硬限制范围内的值,非特权进程可以降低其硬限制(该操作不可逆)。特权进程(在 Linux 下:具有 CAP_SYS_RESOURCE 功能的进程)可以对任一限制值进行任意更改。通过 fork 创建的子进程继承其父进程的资源限制。execve 系统调用会保留资源限制。

getrlimit()setrlimit() 系统调用是用来获取、设置 rlimit(资源限制)的,而 shell 的 ulimit 内置命令其实是 getrlimit()、setrlimit() 的包装。有必要强调一点,每个进程的 rlimit 都是互不影响的,你设置你的,我设置我的。而又因为子进程的 rlimit 是从父进程继承过来的,所以在 shell 中使用 ulimit 修改 shell 进程的 rlimit 会影响到由该 shell 进程启动的进程的 rlimit 值。

ulimit 常用参数:

  • ulimit -a:查看当前 shell 的所有资源限制,默认显示软限制
  • ulimit -Sa:查看当前 shell 的所有资源限制,-S 表示显示软限制
  • ulimit -Ha:查看当前 shell 的所有资源限制,-H 表示显示硬限制
  • ulimit -n:显示当前可打开的文件描述符数量,软限制
  • ulimit -Hn:显示当前可打开的文件描述符数量,硬限制
  • ulimit -n 10240:修改可打开的文件描述符数为 10240,默认软限制,除非指明参数 -H
  • ulimit -Hn 51200:修改可打开的文件描述符数为 51200,硬限制(如果是提高硬限制,则需要 root 权限)
  • ulimit -s 102400:修改堆栈大小的软限制为 102400 kbytes 即 100 MB
  • ulimit -Hs unlimited:修改堆栈大小的硬限制为 unlimited,即不限制上限

limits.conf

sysvinit
主配置文件:/etc/security/limits.conf及分段配置文件:/etc/security/limits.d/*.conf

当用户登录 shell 时:

  • 先应用/etc/security/limits.conf中的限制值,包括软限制和硬限制;
  • 然后再应用/etc/profile/etc/bashrc~/.bash_profile~/.bashrc中的限制。

修改/etc/security/limits.conf文件后,需要重新登录 shell 才能生效,而ulimit是立即生效的。

limits.conf 语法:<domain> <type> <item> <limit>

  • domainusername@groupname*所有用户;
  • typesoft软限制、hark硬限制、-软限制和硬限制;
  • item:常用的有:nofile文件描述符、stack栈大小(KB)、nproc进程数量;
  • limit:整型数值,如果为无限制,可以使用unlimited表示;

特别的,nofile 不仅取决于 /etc/security/limits.conf 的限制,还与内核可打开的文件描述符数目有关;
也就是说,当前系统可打开的最大文件描述符数量不可大于内核能够打开的文件描述符数量,这个值与内核参数有关;

修改内核参数
在 /etc/sysctl.conf 中添加fs.file-max = 10240000,然后使用sysctl -p可立即生效,否则重启后才能生效。
查看当前文件描述符使用情况:cat /proc/sys/fs/file-nr:三个值分别表示:已分配的句柄数、已分配未使用的句柄数、file-max 值。

CentOS 的 ulimit 配置例子:

systemd
如果你的 Linux 发行版使用 systemd 管理系统(如 CentOS7、ArchLinux 等),不再建议使用 /etc/security/limits.conf 文件;
而是应该修改 /etc/systemd/system.conf(系统实例) 或 /etc/systemd/user.conf(用户实例),在 ArchLinux 中,只能这么做。

但是,system.conf 或 user.conf 中无法为每个用户、用户组单独配置资源限制值,在这里修改后,每个用户都是一样的限制:

  • stack:DefaultLimitSTACK=100M:infinity,注意无限制是 infinity 而不是 unlimited;
  • nofile:DefaultLimitNOFILE=102400:infinity,注意无限制是 infinity 而不是 unlimited;
  • nproc:DefaultLimitNPROC=infinity:infinity,注意无限制是 infinity 而不是 unlimited;

修改后只能重启系统生效:systemctl reboot