系统重启后Nginx的Max open files limit被重置为默认的问题

      访问: 1,189 次      评论    

运行环境:CentOS release 6.9 (Final) ,Amazon Linux AMI 2017.09

1、问题

使用 yum 安装的Nginx,会在系统 service 中添加 rc.d 启动脚本,以便在系统重启时,随系统自动启动Nginx。

但随系统自动启动的Nginx,其Max open files limit 是系统默认的1024/4096(并不是我们在 /etc/security/limits.conf 中配置的数字):

所以在访问量不大的情况下,你都会在nginx error log 中,发现"worker_connections exceed open file resource limit: 1024"的报警:

2017/12/28 11:53:20 [warn] 5765#5765: 8192 worker_connections exceed open file resource limit: 1024

你可能会觉得很奇怪,我明明在 /etc/security/limits.conf  中设置了nofile  131072 参数啊,而且这个设置也一直都生效的(ulimit -n 检查OK),之前手动启动Nginx也都是应用这个nofile 设置的。

$ cat /etc/security/limits.conf 
# /etc/security/limits.conf
#
#<domain>      <type>  <item>         <value>
#
*  -  nofile  131072

其实,这个问题也存在于随系统启动的其他服务,如Apache。到底怎么回事呢?

2、解惑

问题出在Linux系统启动过程中,也就是说Nginx主进程启动时,上面的限制配置没有生效;实际上系统启动后执行用户登录login时才会使 limits.conf 配置生效。

简单描述一下,Linux内核启动后的系统启动过程如下:

  1. 运行/sbin/init 程序,执行系统的1号进程(此后系统的控制权就交给 /sbin/init 进程了)

  2. 读取 /etc/inittab 来确定系统启动级别(例如 读取到的默认级别是3)

  3. 执行初始化系统脚本 /etc/rc.d/rc.sysinit 来进行系统配置初始化

  4. 执行 /etc/rc.d/rc 脚本,根据启动级别,执行/etc/rc.d/rc*.d/ 下的各种服务启动脚本(比如 rc3.d下的文件)

  5. 执行 /etc/rc.d/rc.local 脚本(其实是/etc/rc.d/rc*.d/ 下的最后一个脚本,即S99local)

  6. 完成了所有的启动任务后,Linux会启动终端或X-Window来等待用户登录。

至此系统启动过程完成,当用户登录时,才会执行/etc/profile,~/.bash_profile和~/.bashrc 环境配置文件等;

关键一点是用户登陆时才会使 /etc/security/limits.conf 配置文件生效,这个比Nginx进程启动晚,此时的ulimit -n查到的值不是Nginx进程启动时的值。

这里简单扩展一下Linux是如何加载这个 limits.conf 文件的:

$ cat /etc/pam.d/login
#%PAM-1.0
...
account    include      system-auth
password   include      system-auth
session    include      system-auth
...

$ cat /etc/pam.d/system-auth
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
...
session     required      pam_limits.so
...

$ grep -a "/etc/security/limits.conf" /lib64/security/pam_limits.so
#结果见下图

3、解决

1)登录系统,手动运行 service nginx restart 重启Nginx服务

可以解决上述问题,因为此时 limits.conf 配置已经生效。

但是这个方法每次系统重启都要手动执行,有时忘了就麻烦了,甚至机器多的时候更糟糕。

2)在 /etc/rc.local 设置Nginx重启命令,并在 Nginx 启动前执行 ulimit 命令

$ tail /etc/rc.local 
# for nginx
ulimit -SHn 131072
service nginx restart

可以解决上述问题。

注:仅仅在 /etc/rc.local 中添加 service nginx restart 命令是不行的。

3)有人说 Nginx 有个配置文件参数 worker_rlimit_nofile

经实测,无法解决上述 Nginx 随系统 service 自动启动时ulimit -n 不生效的问题。


添加新评论