Home > Linux, 杂七杂八 > 老生常谈: ulimit问题及其影响

老生常谈: ulimit问题及其影响

June 20th, 2011

原创文章,转载请注明: 转载自系统技术非业余研究

本文链接地址: 老生常谈: ulimit问题及其影响

ulimit最初设计是用来限制进程对资源的使用情况的,因为早期的系统系统资源包括内存,CPU都是非常有限的,系统要保持公平,就要限制大家的使用,以达到一个相对公平的环境。以下是典型的机器默认的限制情况:

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 204800
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 204800
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

但是很多年过去了,情况发生变化了,硬件在过去的时间里面发展的非常迅猛,一个拥有几十个核心的,上百G内存的机器差不多也是白菜价格了。但是软件的限制还是没怎么发生变化,导致一系列使用的问题。其中很重要的文件句柄使用限制尤为明显。

特别是类似web服务器,数据库程序等需要大量的文件句柄,一旦开太小,比如默认(1024),在句柄使用完毕的时候,系统就频繁出现emfile错误
,这时候系统很容易陷入不可用。但是如果设定太大了,又会有这样的副作用。很多服务器程序是事件派遣的,比如说用epoll,程序在启动的时候通常会根据最大的文件句柄数来预留内部的slot,比如说Erlang一个slot貌似要占用几K的资源,如果你设定文件句柄数目太大,就可能无端的浪费了几百M内存。所以要正视这个问题,设定一个合适的值。

通常我们是在shell下用来ulimit -n NNNN来设定新开的进程的文件句柄的限制,但是在一个生产环境下会有如下麻烦:

$ ulimit -n 22222222
-bash: ulimit: open files: cannot modify limit: Operation not permitted
$ sudo ulimit -n 22222222
sudo: ulimit: command not found

JulyClyde(julyclyde@gmail.com)同学介绍解释了这个问题:

shell里不能直接更改,是因为登录的时候pam已经从limits.conf中设置了上限,ulimit命令只能在低于上限的范围内发挥了。

这时候我们通常需要修改/etc/security/limits.conf

# 确认包含下面的内容:
* soft nofile NNNNN
* hard nofile NNNNN

修改后,重现登录shell, 用ulimit -Hn和ulimit -Sn确认修改已生效.

另外淘宝雕梁说:

在linux kernel 2.6.25之前通过ulimit -n(setrlimit(RLIMIT_NOFILE))设置每个进程的最大打开文件句柄数不能超过NR_OPEN (1024*1024),也就是100多w(除非重新编译内核),而在25之后,内核导出了一个sys接口可以修改这个最大值(/proc/sys/fs /nr_open).具体的changelog在这里

直接在你自己的程序里面绕开文件句柄的限制。

祝大家玩得开心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

Categories: Linux, 杂七杂八 Tags: ,
  1. JulyClyde
    June 20th, 2011 at 18:08 | #1

    shell里不能直接更改,是因为登录的时候pam已经从limits.conf中设置了上限,ulimit命令只能在低于上限的范围内发挥了。

    Yu Feng Reply:

    对的。。。

    JulyClyde Reply:

    不过我突然想不起来,后台服务从root启动然后setuid到自己的低权限用户,貌似也受这个影响,但不知道在pam里对应的是哪个服务

    JulyClyde Reply:

    哦,他们大概是先setrlimit然后setuid的

  2. kilnt
    June 21st, 2011 at 00:50 | #2

    ACE 这种玩意还有自己的一套 FD 设置 编译进去,更是抓狂.

  3. rr
    June 22nd, 2011 at 15:11 | #3

    taobao所有的开发同学都应该看看。。。

  4. chenryn
    October 25th, 2012 at 15:15 | #4

    想用systemtap修改已经在运行中的进程的max open files,看tapset里有task_max_file_handles()是直接kread(&(f->max_fds))的,但是改成kwrite(&(f->max_fds), 65535)会报错。很难找到kwrite的例子。老大有这么用过么?

    Yu Feng Reply:

    修改要-g guru模式。

  5. September 3rd, 2013 at 11:00 | #5

    找这玩意找了很久,文章真是深入浅出超霸气!
    \(*´▽`)/

  6. September 3rd, 2013 at 11:03 | #6

    不好意思,刚刚发评论的时候页面返回 500 错误,以为没有发成功,所以后来又发了一条。抱歉!@higkoo

    Yu Feng Reply:

    不好意思,WP评论默认要审核的好像. 多谢兄台褒扬.

  7. November 4th, 2015 at 14:00 | #7

    原来kernel引起的…

  8. zhengqian
    February 16th, 2016 at 09:44 | #8

    数据库程序等需要大量的文件句柄,一旦开太小,比如默认(1024),在句柄使用完毕的时候,系统就频繁出现emfile错误

    这里的句柄数应该是系统的句柄数吧?如果是系统的句柄数达到的了上限的话系统错误应该是enfile。

Comments are closed.