开发者社区> 技术小阿哥> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

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

简介:
+关注继续查看

/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,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
【Linux学习 】Linux使用Script命令来记录并回放终端会话
[TOC] 一、背景 在之前的博客 【Git学习-->如何通过Shell脚本实现 监控Gitlab备份整个过程并且通过邮件通知得到备份结果?】 里面,我已经详细记录了每天的自动备份与清理过期备份文件的工作。
2959 0
文章
问答
文章排行榜
最热
最新
相关电子书
更多
ECS系统指南之Linux系统诊断
立即下载
从 Linux 系统内核层面来解决实际问题的实战经验
立即下载
ECS运维指南 之 Linux系统诊断
立即下载