+86 135 410 16684Mon. - Fri. 10:00-22:00

修改Linux FileDescription上限时的误区

修改Linux FileDescription上限时的误区

修改Linux FileDescription上限时的误区

1个进程能同时使用的File Description上限数的修改方法及修改时的注意事项。

在Linux系统能同时使用的File Description数是有上限的,系统整体的上限可在/proc/sys/fs/file-max文件里确认,有大量访问的服务器上会修改/etc/sysctl.conf文件来提高上限。

系统能使用的File Description上限之外,还有1个能使用的File Description的上限,而1个进程能使用的默认上限是1024。

当超过这个上限时,服务器的系统日志里会出现以下错误。

[ERROR] ・・・ Unable to open a passive connection: Too many open files in system ・・・ [ERROR] ・・・ failed to open stream: Too many open files ・・・

一般我们会使用以下方法修改1个进程可使用的File Description上限数

  • 使用ulimit -n命令暂时修改上限
  • 修改/etc/security/limits.conf文件

环境

  • 环境:Amazon EC2 t2.micro
  • 系统:CentOS 6.5 64位
  • Web:HTTPD2.4
  • PHP:5.3.3

ulimit是什么

ulimit是Shell的built-in命令,控制给进程分配的各种资源。(csh是使用limit命令)

用ulimit -n命令可以查看现在的File Description数上限(SoftLimit及HardLimit)。SoftLimit的值应小于HardLimit的值,并且 SoftLimit的值是一般用户也可修改。而HardLimit是只有root用户可以修改。

limits.conf是什么

/etc/security/limits.conf是,PAM认证模块之一的pam_limits的配置文件。配置文件的格式如下;

<domain> <type> <item> <value>

根据以上格式配置的话

root soft nofile 4096
root hard nofile 4096

即root用户执行的进程的最大File Description数是4096。

pam_limits模块,以session类型定义于PAM的配置文件/etc/pam.d/system-auth里,/etc/pam.d /login、/etc/pam.d/sshd、/etc/pam.d/sudo等多个配置文件以Include形式读取system-auth文件。

因此ulimit -n命令会在用户登录或者发生PAM认证(且在session里pam_limits模块被qeruire)时才会生效。

这就意味着「不进行PAM认证的Daemon类进程的上线,不能在/etc/security/limits.conf文件里修改」。

修改limits.conf后的误区(1)

修改limits.conf文件

# vi /etc/security/limits.conf
* soft nofile 2048
* hard nofile 2048

之后,su(SwitchUser)到root之后,ulimit -n命令进行变更确认。

$ sudo su -
Last login: Thu Jul 30 05:03:23 UTC 2015 on pts/0
# ulimit -n
2048
但是用户登录或者su时需要PAM认证(limits.conf配置文件的内容生效),而这和从rc脚本及Daemontools被启动的进程的运行环境是截然不同。

修改limits.conf后的误区(2)

修改limits.conf文件之后,重启Daemon之后会发现不再出现「Too many open files」错误了。

例如使用sudo service httpd restart

  1. sudo到root用户时的PAM认证,会使limits.conf文件生效
  2. root用户启动httpd时,File Description的上限会被子进程(httpd)继承
  3. 在脚本里进行httpd的停止/启动时,httpd进程会继承父进程的File Description上限值
  4. httpd进程启动时继承了父进程的上限值

在Apache上限1024系统上,做了个简单的测试

1. 准备一个会同时使用1024个File Description的PHP脚本(index.php)

<?php
$fp = array();
for ($i = 0; $i < 1100; $i++) { 
     $fp[] = fopen('index.php', 'r'); } 
     echo '<pre>'; var_dump($fp); echo '</pre>';
 ?>

2. 通过Apache访问刚才的index.php文件

array(1100) {
  [0]=>
  resource(3) of type (stream)
  [1]=>
  resource(4) of type (stream)

~ 省略 ~

 resource(1015) of type (stream)
  [1013]=>
  resource(1016) of type (stream)
  [1014]=>
  bool(false)
  [1015]=>
  bool(false)

~ 省略 ~

没有达到1024上限的理由是,httpd进程本身会使用一些File Description。可使用lsof命令进行查看。

Apache的错误日志(/var/log/httpd/error_log)里出现’Too many open files’

[Thu Jul 30 05:08:00.078564 2015] [:error] [pid 1150] [client X.X.X.X:1703] PHP Warning:  fopen(index.php): failed to open stream: Too many open files in /var/www/html/index.php on line 4

3. 如下修改limits.conf文件

# vi /etc/security/limits.conf
* soft nofile 2048
* hard nofile 2048

4. sudo service httpd restart重启Apache

5. 再次通过Apache访问index.php文件,会发现不再出现’Too many open files’错误

以下是访问index.php的结果。

array(1100) {
  [0]=>
  resource(3) of type (stream)
  [1]=>
  resource(4) of type (stream)

~ 省略 ~

  resource(1101) of type (stream)
  [1099]=>
  resource(1102) of type (stream)
}

6. 重启系统

7. 通过Apache访问index.php文件,会发现使用的File Description达到1000左右时,会出现’Too many open files’错误。

手动启动Apache时limits.conf配置文件是有效的,系统重启时是init启动各种Daemon而这时再也没有PAM认证(即limits.conf配置内容无效),Apache会使用系统默认的上限值1024。

小结

修改Daemon类进程的File Description上限时不能使用/etc/security/limits.conf文件。

或者可以把ulimit -n追加到以下文件

  • daemontools:/service/<服务名>/run文件
  • rc脚本:/etc/init.d/<服务名>文件

修改上限之后,比如查看Apache进程的FileDescription上限时使用如下命令

# cat /proc/`pgrep httpd | head -1`/limits | grep 'open files'
Max open files            1024                 4096                 files

系统使用File Description的情况,用如下命令查看

# cat /proc/sys/fs/file-nr
576     0       99006

CentOS7开始是Systemd启动各种Daemon,用什么方法修改File Description的上限呢。测试之后再和大家分享。