写点什么

一文搞懂 Linux 下 Ulimit 资源限制

发布于: 2021 年 02 月 21 日

运维系统调优的过程中,必然会遇到的一个问题就是资源限制,在 linux 中,ulimit 命令是用于控制 shell 程序的资源限制,它是 linux 的 shell 内建指令(可以用 type 命令查看命令是内建还是外部)


今天详细介绍下 ulimit,通过对各参数的配置实验,详细了解 ulimit 的每条限制参数的意义及作用


配置及生效


配置及生效问题是最常遇到的,所以放在前面


对于 ulimit 的配置,配置文件在/etc/security/limits.conf 以及 limits.d 下面的文件,CentOS6 中,limits.d 下面通常默认是 90-nproc.conf,CentOS7 中,通常是 20-nproc.conf,nproc 是限制每个用户创建进程数的,所以这部分配置通常是限制用户创建进程数的,至于前面的数字,我们通过源码查看



首先看下当前 root 用户的 nproc 设置



root 用户的 nproc 是没限制的,至于为什么是 3616,我们待会儿最后说,现在分别在 limits.conf 和 20-nproc.conf 中对 root 用户的 nproc 进行修改



重新登录后,查看



可以看到,是 20-nproc.conf 文件中的生效


所以上面的数字,没有特殊的意义,多个配置文件的时候,就是起到了顺序的作用


我们都知道,linux 下 limit 的限制是由 pam_limits.so 来执行的,PAM 下次有机会再讲,我们通过查找/etc/pam.d 下面模块中对 pam_limits.so 的调用,看下有哪些模块调用了该库



pam 中的配置分四列:

第一列代表模块类型

第二列代表控制标记

第三列代表模块路径

第四列代表模块参数


从上面可以看到,调用 pam_limits.so 都是 session 的管理方式,session 的管理方式代表这个模块用来定义用户登陆前,及用户退出后所要进行的操作,如登录连接信息,用户数据的打开与关闭,挂载文件系统等


这也就是为什么通过 ulimit 命令修改的配置,只对当前 session 生效,而如果是通过配置文件修改的 ulimit,则需要重新登录会话才能生效,后面实验我们会看到


硬限制和软限制


ulimits 的限制分为硬限制和软限制,这里并不是硬件的限制和软件的限制的意思,硬限制是可以在任何时候任何进程中设置,但硬限制只能由超级用户,也就是 root 用户进行设置,软限制是内核实际执行的限制,任何进程都可以将软限制设置为任意小于等于对进程限制的硬限制的值,说白了,硬限制是个硬指标,root 用户设置后,其他用户配置的软限制不能超过这个值,硬限制用-H 参数,软限制用-S 参数,如果不指定参数,会同时把两类限制都改掉,比如 root 用户修改 open files 硬参数



接着切换到 nginx 用户,修改 open files 参数,指定的值超过硬限制,提示不允许操作



指定不超过硬限制的值,则可以正常修改



接着修改软限制值小于硬限制



同样 root 用户也没办法将软限制设置为大于硬限制



有些文章中说,普通用户可以缩小硬限制,但是不能扩大硬限制,这边尝试了下



似乎行不通,接着直接不指定参数测试



不指定-H 参数的话,可以将参数值改为小于 root 设置的硬参数值,但是大于的话,就会提示不允许修改


然后测试的过程中你会发现,在普通用户下,修改了不管是硬参数还是软参数,退出当前 session,之后,重新切换到该用户之后,ulimit 参数又变回到配置文件中的设定,这里就又回到上面说的 pam_limits.so 的调用中,sudo 模块中有调用 pam_limits.so 模块,关于用户登录 session,可以看一下之前的一篇文章"我的服务器被登录了吗?"


unlimited 是多少


通过 ulimit -a 可以看到当前 session 的所有 ulimit 配置中



可以看到很多 unlimited,这些 unlimited 表示就是不限制的意思,这里要说的 ulimited 是多少,指的是上面提到的,nproc 的不限制


上面配置 root 的 nproc 为 unlimited 的时候,我们看到 ulimit -a 查看显示 3616



这个 3616 到底是怎么来的,我们通过分析内核参数,可以发现在 fork.c 中有这么一段定义 RLIMIT_NPROC 的



可以看到默认的值是 max_threads/2,接着分析下 max_threads,其中 mempages 是机器的物理页面个数,THREAD_SIZE 是 8K,通过 ulimit -s 查看,PAGE_SIZE 是 4k,通过 getconf PAGESIZE 查看


我们算下

max_threads=mempages(2592368 kB)/(8/4)/8=162023



而 nproc 需要 max_threads/2,这样算下来和 3616 相差有点远


最后发现,可以通过查看/proc/sys/kernel/thread-max 的值来作为 max_threads 的话,正好符合 nproc 的值



查了另外一个系统,同样



所以这里没太查明白 fork.c 中定义的这个 max_threads 值到底是怎么计算的,反正目前看是有 threads-max 来确定 nproc 大小的,如果设置为不限制的情况下


如果有了解的同学,欢迎下面留言讨论


接着就是介绍各参数的作用,其实通过 help ulimit,可以很清楚的看到里面对于每个参数的解释



所以这里就只是对每个参数进行一个实验性的修改测试,看下具体会影响到哪些情况,我们就以 ulimit -a 显示的顺序在下篇文章中介绍


发布于: 2021 年 02 月 21 日阅读数: 47
用户头像

有一点想法的电脑维修工 2020.07.14 加入

一位有些想法的技术爱好者

评论

发布
暂无评论
一文搞懂Linux下Ulimit资源限制