天天看点

Linux 打开文件数1024限制的原理以及解决办法

/proc/sys/fs/file-max 

该文件指定了可以分配的文件句柄的最大数目。

查看最大值:

1

2

3

<code>[root@localhost home]</code><code># cat /proc/sys/fs/file-max </code>

<code>100977</code>

<code>[root@localhost home]</code><code>#</code>

这表明这台Linux系统最多允许同时打开(即包含所有用户打开文件数总和)100977个文件,是Linux系统级硬限制,所有用户级的打开文件数限制都不应超过这个数值。通常这个系统级硬限制是Linux系统在启动时根据系统硬件资源状况计算出来的最佳的最大同时打开文件数限制,如果没有特殊需要,不应该修改此限制,除非想为用户级打开文件数限制设置超过此限制的值。这个参数的默认值是跟内存大小有关系的,增加物理内存以后重启机器,这个值会增大。大约1G内存10万个句柄的线性关系。

修改值:

如果用户得到的错误消息声明,类似”too many open files”,这是由于打开文件数已经达到了最大值,从而他们不能打开更多文件,则可能需要增加该值。

4

5

6

7

8

9

10

11

12

13

<code>[root@localhost home]</code><code># vim /etc/rc.local </code>

<code>#!/bin/sh</code>

<code>#</code>

<code># This script will be executed *after* all the other init scripts.</code>

<code># You can put your own initialization stuff in here if you don't</code>

<code># want to do the full Sys V style init stuff.</code>

<code>echo</code> <code>222158 &gt; </code><code>/proc/sys/fs/file-max</code>    <code>;添加此项,修改</code><code>file</code><code>-max值</code>

<code>touch</code> <code>/var/lock/subsys/local</code>

<code>[root@localhost home]</code><code># reboot</code>

<code>[root@localhost ~]</code><code># cat /proc/sys/fs/file-max </code>

<code>222158</code>

<code>[root@localhost ~]</code><code>#</code>

修改此硬限制的方法是修改/etc/rc.local脚本,在脚本中添加如下行:

echo 22158 &gt; /proc/sys/fs/file-max

这是让Linux在启动完成后强行将系统级打开文件数硬限制设置为22158。修改完后保存此文件。

/proc/sys/fs/file-nr 

该文件与 file-max 相关,它有三个值: 

已分配文件句柄的数目     已使用文件句柄的数目     文件句柄的最大数目 

该文件是只读的,仅用于显示信息。

<code>[root@localhost ~]</code><code># cat /proc/sys/fs/file-nr </code>

<code>2112    0   222158</code>

修改系统文件打开数:

通过修改/etc/security/limits.conf文件,来修改当前系统文件打开数,limits.conf的格式如下:  

&lt;domain&gt;      &lt;type&gt;  &lt;item&gt;         &lt;value&gt;

&lt;domain&gt; :可以指定单个用户名、@组名、所有用户(*)

<code>[root@localhost ~]</code><code># vim /etc/security/limits.conf   ;文末添加以下两项</code>

<code>* hard nofile 65536       </code>

<code>* soft nofile 65536       ;或者直接使用* - nofile 65536</code>

<code>:wq</code>

我的是RedHat5.4修改后需要重新登陆,有的系统可能需要重启生效,

如果要修改max user processes 值,还需加上以下

* hard nproc 65535

* soft nproc 65535

nofile对应open_files

nproc对应max_user_processes

如果切换到其他非root用户对应的max_user_processes没改变,还需要修改以下文件

/etc/security/limits.d/90-nproc.conf  (centos6)

/etc/security/limits.d/20-nproc.conf   (centos7)

<code>[root@localhost ~]</code><code># cat /etc/security/limits.d/20-nproc.conf </code>

<code># Default limit for number of user's processes to prevent</code>

<code># accidental fork bombs.</code>

<code># See rhbz #432903 for reasoning.</code>

<code>*          soft    nproc     65535</code>

<code>root       soft    nproc     unlimited</code>

要使 limits.conf 文件配置生效,必须要确保 pam_limits.so 文件被加入到启动文件中。查看 /etc/pam.d/login 文件中是否有以下选项,没有直接文末添加:

<code>[root@localhost ~]</code><code># cat /etc/pam.d/login |grep "pam_limits.so"</code>

<code>session required </code><code>/lib/security/pam_limits</code><code>.so</code>

这是告诉Linux在用户完成系统登录后,应该调用pam_limits.so模块来设置系统对该用户可使用的各种资源数量的最大限制(包括用户可打开的最大文件数限制),而pam_limits.so模块就会从/etc/security/limits.conf文件中读取配置来设置这些限制值。

问题:修改完发现系统在本地无法登陆,远程可以登陆,后来查看了下日志如下

14

15

16

17

18

19

20

21

22

<code>[root@mail ~]</code><code># cat /var/log/secure</code>

<code>...</code>

<code>Nov 19 13:17:23 mail sshd[3000]: error: Bind to port 22 on 0.0.0.0 failed: Address already </code><code>in</code> <code>use.</code>

<code>Nov 19 13:17:38 mail runuser: pam_unix(runuser-l:session): session opened </code><code>for</code> <code>user amavis by (uid=0)</code>

<code>Nov 19 13:17:40 mail runuser: pam_unix(runuser-l:session): session closed </code><code>for</code> <code>user amavis</code>

<code>Nov 19 13:17:40 mail runuser: pam_unix(runuser-l:session): session opened </code><code>for</code> <code>user dspam by (uid=0)</code>

<code>Nov 19 13:17:41 mail runuser: pam_unix(runuser-l:session): session closed </code><code>for</code> <code>user dspam</code>

<code>Nov 19 13:17:54 mail login: PAM unable to dlopen(</code><code>/lib/security/pam_limits</code><code>.so)</code>

<code>Nov 19 13:17:54 mail login: PAM [error: </code><code>/lib/security/pam_limits</code><code>.so: wrong ELF class: ELFCLASS32]</code>

<code>Nov 19 13:17:54 mail login: PAM adding faulty module: </code><code>/lib/security/pam_limits</code><code>.so</code>

<code>Nov 19 13:17:57 mail login: pam_unix(login:session): session opened </code><code>for</code> <code>user root by LOGIN(uid=0)</code>

<code>Nov 19 13:17:57 mail login: Module is unknown</code>

<code>Nov 19 13:17:59 mail login: PAM unable to dlopen(</code><code>/lib/security/pam_limits</code><code>.so)</code>

<code>Nov 19 13:17:59 mail login: PAM [error: </code><code>/lib/security/pam_limits</code><code>.so: wrong ELF class: ELFCLASS32]</code>

<code>Nov 19 13:17:59 mail login: PAM adding faulty module: </code><code>/lib/security/pam_limits</code><code>.so</code>

<code>Nov 19 13:18:03 mail login: pam_unix(login:auth): authentication failure; </code><code>logname</code><code>=LOGIN uid=0 euid=0 </code><code>tty</code><code>=tty1 ruser= rhost=  user=csdp</code>

<code>Nov 19 13:18:05 mail login: FAILED LOGIN 1 FROM (null) FOR csdp, Authentication failure</code>

<code>Nov 19 13:18:22 mail sshd[3551]: Accepted password </code><code>for</code> <code>root from 10.15.44.69 port 57696 ssh2</code>

<code>Nov 19 13:18:22 mail sshd[3551]: pam_unix(sshd:session): session opened </code><code>for</code> <code>user root by (uid=0)</code>

<code>Nov 19 13:18:29 mail login: pam_unix(login:session): session opened </code><code>for</code> <code>user root by LOGIN(uid=0)</code>

<code>Nov 19 13:18:29 mail login: Module is unknown</code>

Nov 19 13:17:54 mail login: PAM [error: /lib/security/pam_limits.so: wrong ELF class: ELFCLASS32]

<code>[root@mail ~]</code><code># getconf LONG_BIT</code>

<code>64</code>

<code>[root@mail ~]</code><code>#</code>

系统是64位的,上面/etc/pam.d/login应该修改成64位文件所在目录,即

<code>session required </code><code>/lib64/security/pam_limits</code><code>.so</code>

修改后恢复正常

内核参数对文件描述符也有限制,如果设置的值大于内核的限制,也是不行的,

查找file-max的内核参数:

<code>[root@alille-654-1-41-1 bin]</code><code># sysctl -a|grep file-max</code>

<code>fs.</code><code>file</code><code>-max = 753776</code>

<code>[root@alille-654-1-41-1 bin]</code><code>#</code>

更改file-max的内核参数:

<code>[root@alille-654-1-41-1 bin]</code><code># sysctl -w file-max=65535    ;临时</code>

<code>[root@alille-654-1-41-1 bin]</code><code># vim /etc/sysctl.conf         ;永久</code>

<code>fs.</code><code>file</code><code>-max = 65535</code>

23

24

<code>2112    0   100977</code>

<code>[root@localhost ~]</code><code># ulimit -a    ;显示目前资源限制的设定</code>

<code>core </code><code>file</code> <code>size          (blocks, -c) 0   </code>

<code>data seg size           (kbytes, -d) unlimited  </code>

<code>scheduling priority             (-e) 0</code>

<code>file</code> <code>size               (blocks, -f) unlimited  </code>

<code>pending signals                 (-i) 7922</code>

<code>max locked memory       (kbytes, -l) 64</code>

<code>max memory size         (kbytes, -m) unlimited</code>

<code>open</code> <code>files                      (-n) 1024                ;打开限制</code>

<code>pipe size            (512 bytes, -p) 8</code>

<code>POSIX message queues     (bytes, -q) 819200</code>

<code>real-</code><code>time</code> <code>priority              (-r) 0</code>

<code>stack size              (kbytes, -s) 10240</code>

<code>cpu </code><code>time</code>               <code>(seconds, -t) unlimited</code>

<code>max user processes              (-u) 7922</code>

<code>virtual memory          (kbytes, -</code><code>v</code><code>) unlimited</code>

<code>file</code> <code>locks                      (-x) unlimited</code>

<code>[root@localhost ~]</code><code># ulimit -n</code>

<code>1024</code>

如果需要临时修改文件数可以使用以下操作:

<code>[root@localhost ~]</code><code># ulimit -HSn 4096</code>

<code>4096</code>

H指定了硬性大小,S指定了软性大小,n表示设定单个进程最大的打开文件句柄数量,永久修改参考上面:修改系统文件打开数

如何查看当前系统打开文件数最多的程序:

lsof -n 不将IP转换为hostname,缺省是不加上-n参数 eg:# lsof  /GTES11/

lsof -i 用以显示符合条件的进程情况  eg:# lsof -i :22

<code>[root@localhost ~]</code><code># lsof -n|awk '{print $2}'|sort -nr|uniq -c|sort -nr|head -5</code>

<code>    </code><code>162 1812</code>

<code>    </code><code>149 1827</code>

<code>    </code><code>126 1591</code>

<code>    </code><code>107 1823</code>

<code>    </code><code>100 1826</code>

如何查看某一程序打开文件数:lsof -p pid

<code>[root@localhost ~]</code><code># lsof -p 1812|wc -l</code>

<code>163</code>

<code>[root@localhost ~]</code><code># lsof -p 1827|wc -l</code>

<code>150</code>

查看某一程序最大打开文件数:[root@alille-654-1-41-1 bin]# cat /proc/pid/limits 

<code>[root@alille-</code><code>654</code><code>-</code><code>1</code><code>-</code><code>41</code><code>-</code><code>1</code> <code>bin]# ps -ef|grep -i </code><code>"ProxyServer"</code>

<code>root     </code><code>12091</code> <code>12083</code> <code>99</code> <code>10</code><code>:</code><code>25</code> <code>pts/</code><code>0</code>    <code>05</code><code>:</code><code>32</code><code>:</code><code>45</code>  <code>proxyserver</code>

<code>[root@alille-</code><code>654</code><code>-</code><code>1</code><code>-</code><code>41</code><code>-</code><code>1</code> <code>bin]# cat /proc/</code><code>12091</code><code>/limits </code>

<code>Max open files            </code><code>65535</code>                <code>65535</code>                <code>files</code>

 ulimit 命令详解

ulimit用于shell启动进程所占用的资源,是shell内建命令。

参数介绍:

-H 设置硬件资源限制.

-S 设置软件资源限制.

-a 显示当前所有的资源限制.

-c size:设置core文件的最大值.单位:blocks

-d size:设置数据段的最大值.单位:kbytes

-f size:设置创建文件的最大值.单位:blocks

-l size:设置在内存中锁定进程的最大值.单位:kbytes

-m size:设置可以使用的常驻内存的最大值.单位:kbytes

-n size:设置内核可以同时打开的文件描述符的最大值.单位:n

-p size:设置管道缓冲区的最大值.单位:kbytes

-s size:设置堆栈的最大值.单位:kbytes

-t size:设置CPU使用时间的最大上限.单位:seconds

-v size:设置虚拟内存的最大值.单位:kbytesLinux

启用记录Core dump文件功能

在linux下,设置core文件打开之后,当进程异常退出时,操作系统会在进程工作目录下,生成一个core 文件,文件名一般是:core.进程号。

一、启用记录Core文件功能

通过linux的ulimit命令用 –c参数设置core文件的大小,如:ulimit  –c unlimited 则表示不限制core文件的大小,设置具体的数值表示core文件的字节数。

a、查看当前是否已经打开了此开关

<code>[root@localhost ~]</code><code># ulimit -c</code>

<code>0</code>

ulimit -c 如果输出为 0 ,则代表没有打开。如果为unlimited则已经打开了

 b、开启

临时开启:

<code>[root@localhost ~]</code><code># ulimit -c unlimited</code>

<code>unlimited</code>

<code>[root@localhost ~]</code><code># ulimit -c 0</code>

通过ulimit -c unlimited命令打开此功能,切不限制core文件的大小,如果要取消,执行命令ulimit -c 0 就可以了

永久开启:

在/etc/profile文件中一般可以找到:ulimit -S -c 0 &gt; /dev/null 2&gt;&amp;1,根据上面的例子,我们只要把那个0 改为 unlimited 就ok了,如果没有直接在文末添加,然后保存退出。通过source /etc/profile 使当期设置生效,重启系统

<code>[root@localhost ~]</code><code># vim /etc/profile</code>

<code>ulimit</code> <code>-S -c unlimited</code>

<code>[root@localhost ~]</code><code># source /etc/profile</code>

二、查看Core文件日志方法

通常使用gdb工具察看这个core 文件,gdb是linux自带的一个调试工具,比较容易定位到发生异常的函数名。比如运行一个进程,发生异常退出,则在工作目录下生成一个core.xxxxx的文件,可以运行gdb查看:

gdb 进程名 core.xxxxxx 回车,输入 where 命令,即会列出异常时的函数调用栈。一般为了保证环境一致性,需要在本机上执行gdb察看core文件。

eg:gdb httpd -c core.1309

      Where

core dump文件名的模式保存在/proc/sys/kernel/core_pattern中,缺省值是core。通过以下命令可以更改core dump文件的位置(如希望生成到/tmp/cores目录下)echo “/tmp/cores/core” &gt; /proc/sys/kernel/core_pattern

本文转自 justin_peng 51CTO博客,原文链接:http://blog.51cto.com/ityunwei2017/1558092,如需转载请自行联系原作者

继续阅读