今天在使用 Prometheus 时遇到了问题,报错 err=”list block dirs /prometheus/data/: open /prometheus/data/: too many open files”, 经查询发现,系统默认的普通用户系统最大打开文件数为 1024,Prometheus 数据太多导致该问题,将普通用户的这个限制适当的上调即可。
经过这个事情发现,对 limit 的掌握并不熟悉,特意搜索了 limit 的相关信息整理在这里,学习以及备忘。
环境说明:
1 | CentOS Linux release 7.4.1708 (Core) |
ulimit 命令详解
Linux是有文件句柄限制的,而且Linux默认普通用户都是1024,root 用户没有限制,作为生产系统使用很容易就达到这个数量
操作系统各方面的资源都是非常紧缺的, ulimit 可以起到很大的作用,它是一种简单并且有效的实现资源限制的方式。
ulimit 用于限制 shell 启动进程所占用的资源,支持以下各种类型的限制:所创建的内核文件的大小、进程数据块的大小、Shell 进程创建文件的大小、内存锁住的大小、常驻内存集的大小、打开文件描述符的数量、分配堆栈的最大大小、CPU 时间、单个用户的最大线程数、Shell 进程所能使用的最大虚拟内存。同时,它支持硬资源和软资源的限制。
作为临时限制,ulimit 可以作用于通过使用其命令登录的 shell 会话,在会话终止时便结束限制,并不影响于其他 shell 会话。而对于长期的固定限制,ulimit 命令语句又可以被添加到由登录 shell 读取的文件中,作用于特定的 shell 用户。
参数说明
1 | -a:显示目前资源限制的设定; |
limit.conf 文件说明
limits.conf 文件是 Linux PAM(插入式认证模块,Pluggable Authentication Modules)中 pam_limits.so 的配置文件,pam_limits 模块对用户的会话进行资源限制。对系统访问资源有一定保护作用。
一个 shell 的初始limits就是由 pam_limits 设定的,用户登录后,pam_limits 会给用户的shell设定在 limits.conf 定义的值。
pam_limits模块对用户的会话进行资源限制,然后 /etc/pam.d/ 下的应用程序调用 pam_***.so 模块。
pam_limits 的设定值也是 per-process 的。
pam_limits 的设置是永久生效的。
limit.conf 文件的格式如下:
1 | <domain> <type> <item> <value> |
- <domain> 可以是如下:
1 | - user 可以是一个用户名 |
- <type> 只能是下列三个值之一:
1 | - soft 当前系统生效的设置值 |
- <item> 可以是下列的选项之一:
1 | - core 限制内核文件的大小(KB) - limits the core file size (KB) |
- <value> 可以选择如下之一:
1 | - 0 最小值 |
查看当前 limit 限制
使用 ulimit -a 即可查看当前的 limit ,open files 对应的就是当前登陆用户的最大文件打开数量。(也可以用 ulimit -n 快速查看)
1 | [root@hulk ~]# ulimit -a |
临时修改 limit 限制
很多时候为了检查问题,需要临时修改设置以确认问题的原因,或者不希望永久生效,那么可以使用如下命令进行快速设置
1 | ulimit -n 4096 |
很多文章称 ulimit -n 只允许设置得越来越小,比如先执行了ulimit -n 1000,在执行ulimit -n 1001,就会报 “cannot modify limit: Operation not permitted” 错误。
这个其实也是不准确的说法。首先要搞清楚,任何用户都可以执行ulimit,但root用户和非root用户是非常不一样的。
非root用户只能越设置越小,不能越设置越大。
root 用户没有限制,可以随意增加或者缩小。
永久修改 limit 限制
上述的设置只能临时生效,如果想要永久生效,那么要换其他方法。
想要永久生效,有2种方法。
将上述命令写到登陆后默认加载的文件
该方法对应的操作是,如果需要
所有用户有效,将 ulimit -n 4096 添加到 /etc/profile 。 所有用户登录后都会检查该文件,并加载其中的配置。
特定用户有效,将 ulimit -n 4096 添加到对应用户的 ~/.bash_profile 。 用户登录后都会检查自己家目录下的 .bash* 文件,并加载其中的配置。
个人并不建议使用这种方式进行修改,原因是修改不好或者在某些未考虑周全的情况下,会导致用户无法登录系统,人为增加故障率
修改 limit.conf 配置文件
在 /etc/security/limits.conf 文件中按照文件的规则添加配置例如
设置 test 的最大打开数为8196
1 | test - nofile 8196 |
如果对某一用户或者某中特定的场景有很多的 limit 设置,那么不建议直接修改 /etc/security/limits.conf 文件,这样管理起来成本太大。
这种情况下,可以在 /etc/security/limits.d/ 目录下新建 .conf 结尾的配置文件进行单独管理,pam_limits.so 在执行时也会一并加载。
在系统里,/etc/security/limits.d/ 目录下的文件会覆盖 /etc/security/limits.conf 的内容,所以如果在 limits.conf 文件里配置的内容不要和 limits.d 目录下的内容冲突,如果担心冲突,可以将配置都放在 limits.d 下进行管理。
覆盖的顺序是,
limits.d 目录下的会覆盖 limits.conf 文件。
limits.d 目录下按照英文字母顺序进行加载,后加载的覆盖前边加载的 。
数字应该按照 01 、02、……09、10 这样的顺序进行排序。
修改系统总限制。
上边讲了很多种查看和修改的方法,一般情况下是够用了,那么现在来说说特殊情况。上边提过,最大文件打开数量最大不要超过系统的限制。
那么怎么查看呢?系统将这个数字存储在了 /proc/sys/fs/file-max 文件,直接查看就好。/proc/sys/fs/file-nr 文件里存储了整个系统目前使用的文件句柄数量。
1 | [test@hulk ~]$ cat /proc/sys/fs/file-max |
那么怎么修改这个值呢?有2个方法,一个是临时的,一个是永久的。
临时修改系统限制
1 | echo 6553560 > /proc/sys/fs/file-max |
永久修改系统限制
修改 /etc/sysctl.conf, 加入下列配置,由于修改了系统的内核参数,所以需要使用 sysctl -p 来使新的参数生效。
1 | fs.file-max = 6553560 |
注意
- 数值设置根据实际情况进行设置,不要一味的增大,否则会导致系统故障无法运行;
- 网上说修改了 limit.conf 以后如果要生效,必须要确保 pam_limits.so 文件被加入到启动文件中。查看 /etc/pam.d/login 文件中有:session required /lib/security/pam_limits.so 。我在 CentOS 7 的系统里找了/etc/pam.d/login 文件,发现没有 pam_limits.so , 也可以正常生效;
- 修改系统最大值时或许可以参考本地磁盘或者存储的相关指标,不要“超标”;
- limits.conf 和sysctl.conf区别在于limits.conf是针对用户,而sysctl.conf是针对整个系统参数配置。
参考链接
- http://man.linuxde.net/ulimit
- linux 系统文件 /etc/security/limits.conf
- http://smilejay.com/2016/06/centos-7-systemd-conf-limits/
======================
Erdong, A Linux user !