linux ulimit 调优

linux系统默认open files数目为1024, 有时应用程序会报Too many open files的错误,是因为进程打开了太多的文件,导致open files数目不够。这就需要修改参数进行调优。特别是有大量文件访问的应用,如elasticsearch、filebeat等, 更要注意这个问题。

网上的很多教程,都只是简单的说明如何设置,但很多东西没讲明白,而且有时候设置后却不能生效,关于其验证也比较模糊。这里对使用的一些经验进行整理。

查看进程的limits和打开的文件数

查看filebeat打开的文件数

root@filebeatserver:~# ll /proc/$(pidof filebeat)/fd | wc -l
23
root@filebeatserver:~# cat /proc/3108/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            8388608              unlimited            bytes
Max core file size        0                    unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             4096                 4096                 processes
Max open files            65536                65536                files
Max locked memory         16777216             16777216             bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       128421               128421               signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us

相关参数

关于进程打开文件描述数量限制,有三个相关参数

file-max:系统所有进程一共可以打开的文件数量 ;**这项参数是系统级别的。**系统不一样,默认值不同。

nr_open:单个进程可分配的最大文件数;**这项参数也是系统级别的。**默认:1048576

limits:当前shell以及由它启动的进程的资源限制;**这项参数是用户所在shell或其所启动的进程级别的。**默认:1024

可以简单的下一个大概结论,file-max是内核可分配的最大文件数,nr_open是单个进程可分配的最大文件数,在在配置ulimit时,如果要超过1048576,需要先增大nr_open;并且根据需求调整file-max 。

查看当前配置

# 查看fs.file-max
sysctl -a | grep 'fs.file-max'
# 查看fs.nr_open
sysctl -a | grep 'fs.nr_open'
# 查看limits
ulimit -a | grep "open files"

示例(ubuntu 18):

root@ubuntu18:~# sysctl  -a | grep 'fs.file-max'
fs.file-max = 52706963
root@ubuntu18:~# ulimit -a | grep "open files"
open files                      (-n) 1024
root@ubuntu18:~# sysctl -a | grep 'fs.nr_open'
fs.nr_open = 1048576

Ubuntu 20 的fs.file-max

root@ubuntu20:~# sysctl  -a | grep 'fs.file-max'
fs.file-max = 9223372036854775807

修改file-max参数配置

临时修改,重启失效

echo  167772166 > /proc/sys/fs/file-max  
# 或者
sysctl -w "fs.file-max=167772166"

永久生效

echo "fs.file-max = 167772166 " >> /etc/sysctl.conf
sysctl -p # 立即生效

修改nr_open参数配置

临时修改,重启失效

echo  167772166 > /proc/sys/fs/nr_open
# 或者
sysctl -w "fs.nr_open=167772166"

永久生效

echo "fs.nr_open = 167772166 " >> /etc/sysctl.conf
sysctl -p # 立即生效

修改limits配置

命令行使用ulimit -n 65535,当前shell生效,退出shell失效。或者在诸如.bashrc等登录文件中,使用ulimit -n 65535,也可以修改用的limits配置。

不过,limits配置最佳实践,是修改/etc/security/limits.conf配置文件,除了可以配置open files,还包含nproc memlock等的配置;

修改后生效方法:shell重新登录、sudo或重启进程。

修改方法,/etc/security/limits.conf 尾部追加以下配置:

兼容写法

# 兼容写法,要给root用户和elasticsearch用户优化limits配置
root soft nofile 524288
root hard nofile 524288
root soft nproc 524288
root hard nproc 524288
root soft memlock unlimited
root hard memlock unlimited

elasticsearch soft nofile 524288
elasticsearch hard nofile 524288
elasticsearch soft nproc 524288
elasticsearch hard nproc 524288
elasticsearch soft memlock unlimited
elasticsearch hard memlock unlimited

不兼容写法

# 不兼容写法,修改所有用户;亲测ubuntu 18/20不生效
* soft nofile 524288
* hard nofile 524288
* soft nproc 524288
* hard nproc 524288
* soft memlock unlimited
* hard memlock unlimited

注意:建议使用兼容写法,有些系统对不兼容写法不生效,比如ubuntu 20 使用不兼容写法就不生效

特定服务配置limits

除了在系统中对某用户进行limits配置之外,还可以使用statemd配置,在启动程序时配置limits。配置service时,配置如下参数:

# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=655360
# Specifies the maximum number of processes
LimitNPROC=40960

验证配置

file.file-max 和 file.nr_open验证

这两个参数为系统参数,直接查看系统内核参数即可

# 查看fs.file-max
sysctl -a | grep 'fs.file-max'
# 查看fs.nr_open
sysctl -a | grep 'fs.nr_open'

open file limits验证

这个参数,是用户所在shell或其所启动的进程的参数配置,需要在指定用户shell下或查看进程信息

用户shell下查看

配置完成以后,退出当前shell,重新登录,使用如下命令:

ulimit -a | grep "open files"

或使用sudo 查看指定用户的limits

# 查看elasticsearch的limits参数配置
su  elasticsearch  -s /bin/bash -c "ulimit -a " |grep "open files"

查看进程的limits和打开的文件数

查看filebeat打开的文件数,

首先查看filebeat的PID,然后根据pid查看进程相关信息

# 查看filebeat进程打开的文件数
root@filebeatserver:~# ll /proc/$(pidof filebeat)/fd | wc -l
23
# 查看filebeat进程的limits配置,其中包含'max open files'
root@filebeatserver:~# cat /proc/$(pidof filebeat)/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            8388608              unlimited            bytes
Max core file size        0                    unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             4096                 4096                 processes
Max open files            65536                65536                files
Max locked memory         16777216             16777216             bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       128421               128421               signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us

QA: limits配置后不生效

  1. 确保配置正确,ubuntu一定要使用兼容写法,即指定用户,不要使用*

  2. /etc/security/limits.conf其实是 Linux PAM模块的配置文件,检查pam 模块被正确加载

    1. /etc/ssh/sshd_configUsePAM yes

    2. /etc/pam.d/login /etc/pam.d/system-auth /etc/pam.d/sshd 中包含以下配置

      session
         required     pam_limits.so
      
  3. 其他配置文件,如rc.local .bashrc等文件中写了ulimit -n 65535等配置

关于open file的其他一些内核参数

fs.inotify.max_queued_events:表示调用inotify_init时分配给inotify instance中可排队的event的数目的最大值,超出这个值的事件被丢弃,但会触发IN_Q_OVERFLOW事件。

fs.inotify.max_user_instances:表示每一个real user ID可创建的inotify instatnces的数量上限,默认128.

fs.inotify.max_user_watches:表示同一用户同时可以添加的watch数目(watch一般是针对目录,决定了同时同一用户可以监控的目录数量)