适用范围
适用于linux平台对用户或者程序的资源限制, 或主动限制, 或被动来解决问题.
价值分析
ulimit值从系统层就对程序或者用户对系统资源的利用, 以前关于这些值出过一些问题, 这些值值得关注, 这次我来总结一下以前关于这个出现的问题, 并改变以前的方式, 动态修改程序的ulimit值. 不需要再重启程序了.
问题回顾:
关于打core问题
接触这个问题是2011年接触怪物世界的时候, 都知道ulimit -c unlimited用来启用core生成, 然后用kernel.core_pattern = core-%e来控制生成的格式之类的. 但是这里有个问题可能被很多人忽略了: ulimit -c unlimited位置问题.
ulimit -c unlimited , 我们一般是在/etc/profile里面修改添加. 之前在bash远程ssh审核那里也讲过, 远程执行命令的时候是不会加载/etc/profile的. 这就导致在关键时候程序挂了, 才发现core选项没开启. 这个是指远程开启程序的情况, 因为我们当初是通过ssh ip “command”方式开启程序.
当时问题排查时候当然没那么顺畅, 测试了很久, 最终用set和ulimit -a列举系统参数变量时候发现了ulimit -c的值其实是0. 然后是想办法解决问题, 这个事件是在bash远程ssh审核之前发生的, 所以当时也花费了很多事件研究远程时候文件加载情况. 当时的解决方式比较老式, 发现加载问题之后把ulimit -c unlimited加入到/etc/bashrc里面就可以了. 因为ssh虽然不加载profile文件, 但是还是会加载bashrc文件. 不过经过一些时间之后, 发研究了个比较专业的解决方式: /etc/init.d/sshd 有句[ -f /etc/sysconfig/sshd ] && . /etc/sysconfig/sshd, 所以比较专业的解决方式是像snmp禁日志那样, 在 /etc/sysconfig/sshd加入ulimit -c unlimited这行. 实际测试时候注意重启sshd的时候会当前的ulimit值会影响sshd的ulimit变量.
关于句柄和线程问题
关于句柄问题, 当系统出现retry: Resource temporarily unavailable这类的报错, 大多是系统的硬性限制, 比较常见的是句柄不够, 还表现在用户线程数不够.
创建一个账号test, 在/etc/security/limits.d/90-nproc.conf加入test hard nproc 30, 这样就很严格限制了只能产生30个线程, 测试的话, 一个for循环, 在后台循环40次vi一个文件就重现了bash: fork: retry: Resource temporarily unavailable, 用root账号运行ps -efT |grep ^test | wc -l ,这个值就恰好是30了, 不过用test这个账号是运行不了ps的,因为他的线程已经满了. 刚才是说的max user processes (-u)这个值.
另外句柄问题open files (-n), 简单的就表现在占用多少个文件, 这个文件还包括socket之类的, 在/proc/pid/fd 这个文件夹里面. 重现这个问题也很简单, 恢复之前的配置, 然后修改 /etc/security/limits.conf 文件加入test hard nofile 40, 然后打开很多文件就重现了.
动态修改ulimit值
这次重点是说动态修改ulimit值, 因为之前我的概念也是重启进程, 这里说的动态修改, 不是说在bash里面ulimit去修改, 而是说针对程序, 比如已经运行的一个游戏程序, 肯定不能轻易去重启, 如果瓶颈已经来了, 又要修改怎么办呢, 这次我们说的重点是不重启去修改.
比如刚才test账号的bash已经满了30个线程了, 我们把bash看为一个游戏程序, 已经在运行了, 我们用root账号去修改他的限制.
ps -ef |grep bash|grep ^test 找到test账号的bash程序的pid 26594,然后进入他的”内部”,cd /proc/26594 ,cat limits, 这个文件里面就会发现我们做的ulimit限制都在这里, 所以我们只需要修改这个文件, 但是这里有个大问题, 怎么修改proc文件夹里面的内容, 首先vi是肯定不行的, 比如我们平时修改数据包的中转都是echo一个值进去, 但是这里的内容不一样:
cat limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 10485760 unlimited bytes
Max core file size unlimited unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 30 30 processes
Max open files 10240 10240 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 30504 30504 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
我们需要修改的是这行”Max processes 30 30 processes “
尝试echo正确的值进去, 提示echo: write error: Invalid argument. 行不通. 多多google一下, 发现这个修改有点不一样, echo -n “Max processes=31:31″ >limits, 而且是必需加-n 然后”覆盖”进去.
Ok, 多给了一个线程给test了, 现在test可以多运行一个”线程”了, 这里不是说进程, 可以这样测试一下, 现在用test编辑一个a.sh,内容是sleep 10, 然后保存退出, 运行a.sh就会发现又报错了a.sh: fork: retry: Resource temporarily unavailable, a.sh不能再创建sleep这个线程. 所以上面的ps 要加-T看线程数才能准确查看用户的线程数.
哎, 好久没更新了, 写文档比较麻烦啊, 大概5月16号发. 哈哈