运维系统调优的过程中,必然会遇到的一个问题就是资源限制,在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是限制每个用户创建进程数的,所以这部分配置通常是限制用户创建进程数的,至于前面的数字,我们通过源码查看


搞懂ulimit资源限制_java

从源码中可以看到,是先读取limits.conf,接着如果limits.d目录下有配置文件的话,也会读取,所以意味着limits.d下面的配置会覆盖limits.conf中相同的配置,比如我们在limits.conf中设置root用户的nproc,然后在limits.d下面的配置文件中同样设置root用户的nproc,看下效果,nproc对应的是-u,也就是max user processes


首先看下当前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硬参数

搞懂ulimit资源限制_java_02


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

搞懂ulimit资源限制_java_03


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

搞懂ulimit资源限制_java_04


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

搞懂ulimit资源限制_java_05


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

搞懂ulimit资源限制_java_06


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

搞懂ulimit资源限制_java_07

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

搞懂ulimit资源限制_java_08

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


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





unlimited是多少



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

搞懂ulimit资源限制_java_09

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


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

搞懂ulimit资源限制_java_10


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

搞懂ulimit资源限制_java_11


可以看到默认的值是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

搞懂ulimit资源限制_java_12

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


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

搞懂ulimit资源限制_java_13

查了另外一个系统,同样

搞懂ulimit资源限制_java_14


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


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


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

搞懂ulimit资源限制_java_15


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