Too many open files解决方法

问题

早上到公司发现负责的一个项目打不开了,因为其他项目都依赖于这个模块,所有导致所有项目都无法运行。赶紧排查问题。

首先看了日志,发现报错信息为Too many open files

too many open files问题排查 was too many open files_打开文件

然后查看ulimit命令查看文件配置,如下

too many open files问题排查 was too many open files_开发问题_02


这里发现默认每个进程打开的文件最大个数是1024。

接着我取项目的进程id查看项目打开文件数目,如下

too many open files问题排查 was too many open files_jar_03


发现一共打开了4137个文件资源,超出默认的1024很多。

接着使用lsof -p #port命令查看项目究竟都开了哪些资源文件,如下图所示:

too many open files问题排查 was too many open files_打开文件_04


发现大部分是我一个项目中使用的取IP地址文件,我怀疑是不是没有释放文件IO连接资源所导致的。一看代码,果然是,马上修改,如下:

too many open files问题排查 was too many open files_开发问题_05


写代码还是要小心呀,特别是对资源的操作。

原因

Too many open files是Linux系统中常见的错误,从字面意思上看就是说程序打开的文件数过多,不过这里的files不单是文件的意思,也包括打开的通讯链接(比如socket),正在监听的端口等等,所以有时候也可以叫做句柄(handle),这个错误通常也可以叫做句柄数超出系统限制。

引起的原因就是进程在某个时刻打开了超过系统限制的文件数量以及通讯链接数,通过命令ulimit -a可以查看当前系统设置的最大句柄数是多少:

[tomcat@localhost bin]$ 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) 14732
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) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

open files那一行就代表系统目前允许单个进程打开的最大句柄数,这里是1024。
使用命令lsof -p 进程id可以查看单个进程所有打开的文件详情,使用命令lsof -p 进程id | wc -l可以统计进程打开了多少文件:

Last login: Mon Jun  3 14:37:21 2019 from 172.30.10.233
[root@bogon ~]# jps
121091 Jps
74149 Bootstrap
27780 sca-server.jar
63526 Bootstrap
75271 scc-project.jar
[root@bogon ~]# lsof -p 27780 | wc -l
83

如果文件数过多使用lsof -p 进程id命令无法完全查看的话,可以使用lsof -p 进程id > openfiles.log将执行结果内容输出到日志文件中查看。

解决办法

1、增大允许打开的文件数

命令方式
ulimit -n 2048

这样就可以把当前用户的最大允许打开文件数量设置为2048了,但这种设置方法在重启后会还原为默认值
ulimit -n命令非root用户只能设置到4096。
想要设置到8192需要sudo权限或者root用户。

修改系统配置文件
vim /etc/security/limits.conf  
#在最后加入  
* soft nofile 4096  
* hard nofile 4096

或者只加入

* - nofile 8192

最前的 * 表示所有用户,可根据需要设置某一用户,例如

roy soft nofile 8192  
roy hard nofile 8192

注意”nofile”项有两个可能的限制措施。就是项下的hard和soft。 要使修改过得最大打开文件数生效,必须对这两种限制进行设定。 如果使用”-“字符设定, 则hard和soft设定会同时被设定。

2、检查程序问题

如果你对你的程序有一定的解的话,应该对程序打开文件数(链接数)上限有一定的估算,如果感觉数字异常,请使用第一步的lsof -p 进程id > openfiles.log命令,获得当前占用句柄的全部详情进行分析,

  • 打开的这些文件是不是都是必要的?
  • 定位到打开这些文件的代码
  • 是否程序操作了文件写入,但是没有进行正常关闭
  • 是否程序进行了通讯,但是没有正常关闭(也就是没有超时结束的机制)

如果程序中存在这些问题的话,无论系统句柄数设置的多么大,随着时间的推移,也一定会占用完。