且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-09-20 23:31:29

/proc/sys/fs/file-max 

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

查看最大值:

1
2
3
[root@localhost home]# cat /proc/sys/fs/file-max 
100977
[root@localhost home]#

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

修改值:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@localhost home]# vim /etc/rc.local 
 
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
echo 222158 > /proc/sys/fs/file-max    ;添加此项,修改file-max值
touch /var/lock/subsys/local
[root@localhost home]# reboot
[root@localhost ~]# cat /proc/sys/fs/file-max 
222158
[root@localhost ~]#

修改此硬限制的方法是修改/etc/rc.local脚本,在脚本中添加如下行:
echo 22158 > /proc/sys/fs/file-max
这是让Linux在启动完成后强行将系统级打开文件数硬限制设置为22158。修改完后保存此文件。

/proc/sys/fs/file-nr 

该文件与 file-max 相关,它有三个值: 
已分配文件句柄的数目     已使用文件句柄的数目     文件句柄的最大数目 
该文件是只读的,仅用于显示信息。

1
2
3
[root@localhost ~]# cat /proc/sys/fs/file-nr 
2112    0   222158
[root@localhost ~]#

修改系统文件打开数:

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

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

<domain> :可以指定单个用户名、@组名、所有用户(*)

type:有 soft(指的是当前系统生效的设置值),hard(表明系统中所能设定的最大值)和 -(表明同时设置了 soft 和 hard 的值)

1
2
3
4
[root@localhost ~]# vim /etc/security/limits.conf   ;文末添加以下两项
* hard nofile 65536       
* soft nofile 65536       ;或者直接使用* - nofile 65536
:wq

我的是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)

1
2
3
4
5
6
7
8
[root@localhost ~]# cat /etc/security/limits.d/20-nproc.conf 
# Default limit for number of user's processes to prevent
# accidental fork bombs.
# See rhbz #432903 for reasoning.
 
*          soft    nproc     65535
root       soft    nproc     unlimited
[root@localhost ~]#

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

1
2
3
[root@localhost ~]# cat /etc/pam.d/login |grep "pam_limits.so"
session required /lib/security/pam_limits.so
[root@localhost ~]#

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@mail ~]# cat /var/log/secure
...
Nov 19 13:17:23 mail sshd[3000]: error: Bind to port 22 on 0.0.0.0 failed: Address already in use.
Nov 19 13:17:38 mail runuser: pam_unix(runuser-l:session): session opened for user amavis by (uid=0)
Nov 19 13:17:40 mail runuser: pam_unix(runuser-l:session): session closed for user amavis
Nov 19 13:17:40 mail runuser: pam_unix(runuser-l:session): session opened for user dspam by (uid=0)
Nov 19 13:17:41 mail runuser: pam_unix(runuser-l:session): session closed for user dspam
Nov 19 13:17:54 mail login: PAM unable to dlopen(/lib/security/pam_limits.so)
Nov 19 13:17:54 mail login: PAM [error: /lib/security/pam_limits.so: wrong ELF class: ELFCLASS32]
Nov 19 13:17:54 mail login: PAM adding faulty module: /lib/security/pam_limits.so
Nov 19 13:17:57 mail login: pam_unix(login:session): session opened for user root by LOGIN(uid=0)
Nov 19 13:17:57 mail login: Module is unknown
Nov 19 13:17:59 mail login: PAM unable to dlopen(/lib/security/pam_limits.so)
Nov 19 13:17:59 mail login: PAM [error: /lib/security/pam_limits.so: wrong ELF class: ELFCLASS32]
Nov 19 13:17:59 mail login: PAM adding faulty module: /lib/security/pam_limits.so
Nov 19 13:18:03 mail login: pam_unix(login:auth): authentication failure; logname=LOGIN uid=0 euid=0 tty=tty1 ruser= rhost=  user=csdp
Nov 19 13:18:05 mail login: FAILED LOGIN 1 FROM (null) FOR csdp, Authentication failure
Nov 19 13:18:22 mail sshd[3551]: Accepted password for root from 10.15.44.69 port 57696 ssh2
Nov 19 13:18:22 mail sshd[3551]: pam_unix(sshd:session): session opened for user root by (uid=0)
Nov 19 13:18:29 mail login: pam_unix(login:session): session opened for user root by LOGIN(uid=0)
Nov 19 13:18:29 mail login: Module is unknown
...

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

1
2
3
[root@mail ~]# getconf LONG_BIT
64
[root@mail ~]#

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

1
2
3
[root@localhost ~]# cat /etc/pam.d/login |grep "pam_limits.so"
session required /lib64/security/pam_limits.so
[root@localhost ~]#

修改后恢复正常

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

查找file-max的内核参数:

1
2
3
[root@alille-654-1-41-1 bin]# sysctl -a|grep file-max
fs.file-max = 753776
[root@alille-654-1-41-1 bin]#

更改file-max的内核参数:

1
2
3
[root@alille-654-1-41-1 bin]# sysctl -w file-max=65535    ;临时
[root@alille-654-1-41-1 bin]# vim /etc/sysctl.conf         ;永久
fs.file-max = 65535



linux下面部署应用的时候,有时候会遇上socket/file: can‘t open so many files的问题,其实linux是有文件句柄限制的(就像winxp?),而且默认不是很高,一般都是1024,作为一台生产服务器,其实很容易就达到这个数量,因此我们需要修改上述文件把这个值改大一些。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[root@localhost ~]# cat /proc/sys/fs/file-max 
100977
[root@localhost ~]# cat /proc/sys/fs/file-nr 
2112    0   100977
[root@localhost ~]# ulimit -a    ;显示目前资源限制的设定
core file size          (blocks, -c) 0   
data seg size           (kbytes, -d) unlimited  
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited  
pending signals                 (-i) 7922
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024                ;打开限制
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7922
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
[root@localhost ~]# ulimit -n
1024
[root@localhost ~]#

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

1
2
3
4
[root@localhost ~]# ulimit -HSn 4096
[root@localhost ~]# ulimit -n
4096
[root@localhost ~]#

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

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

lsof(list open files)是一个列出当前系统打开文件的工具。在终端下输入lsof即可显示系统打开的文件,因为 lsof 需要访问核心内存和各种文件,所以必须以 root 用户的身份运行它才能够充分地发挥其功能。 每行显示一个打开的文件,若不指定条件默认将显示所有进程打开的所有文件

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

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

1
2
3
4
5
6
7
[root@localhost ~]# lsof -n|awk '{print $2}'|sort -nr|uniq -c|sort -nr|head -5
    162 1812
    149 1827
    126 1591
    107 1823
    100 1826
[root@localhost ~]#

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

1
2
3
4
5
[root@localhost ~]# lsof -p 1812|wc -l
163
[root@localhost ~]# lsof -p 1827|wc -l
150
[root@localhost ~]#

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

1
2
3
4
[root@alille-654-1-41-1 bin]# ps -ef|grep -i "ProxyServer"
root     12091 12083 99 10:25 pts/0    05:32:45  proxyserver
[root@alille-654-1-41-1 bin]# cat /proc/12091/limits 
Max open files            65535                65535                files

 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、查看当前是否已经打开了此开关

1
2
3
[root@localhost ~]# ulimit -c
0
[root@localhost ~]#

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

 b、开启

临时开启:

1
2
3
4
5
6
7
[root@localhost ~]# ulimit -c unlimited
[root@localhost ~]# ulimit -c
unlimited
[root@localhost ~]# ulimit -c 0
[root@localhost ~]# ulimit -c
0
[root@localhost ~]#

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

永久开启:

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

1
2
3
4
5
6
7
[root@localhost ~]# vim /etc/profile
ulimit -S -c unlimited
:wq
[root@localhost ~]# source /etc/profile
[root@localhost ~]# ulimit -c
unlimited
[root@localhost ~]#


二、查看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” > /proc/sys/kernel/core_pattern




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