解决Linux系统上由于程序占用的文件描述符(file descriptor)过多导致的异常问题

2017-08-31 16:37:27来源:https://www.codelast.com/%e5%8e%9f%e5%88%9b-%e8%a7%a3%e5%86%作者:编码无悔人点击

分享


转载需注明出处:

https://www.codelast.com/


前几天发现服务器上的一个JAVA程序表现很不对劲,运行起来特别“慢”,仔细一看程序的日志,发现里面有Exception抛出,提示“too many open files”,由于无论是读写文件还是创建网络连接,都需要占用文件描述符(fd),于是怀疑是服务器上的某个程序占用的资源没有释放,达到了系统设置的上限从而导致程序异常。



『1』
查看系统open files限制


可以用下面的命令来查看:


ulimit -n


文章来源:
https://www.codelast.com/



『2』
查看系统里占用fd最多的进程


用root用户运行下面的命令,可以打印出每个进程占用的fd数量(从大到小):



lsof -n | awk '{print $2}' | sort | uniq -c | sort -nr | more

部分输出类似于:


12520 16485


125 7054


69 20120


69 15291


65 20113


65 15284


57 19774


......


第一列是占用的fd数量,第二列是进程的pid。最可疑的显然是占用数量最多的头几个进程。



文章来源:
https://www.codelast.com/



『3』
查找出有问题的程序到底在干什么


为便于排查,先从第一个进程查起,如果第一个进程就定位到了问题,那么就不用查后面的了。


ll /proc/16485/fd
部分输出类似于:

lrwx------ 1 root root 64 Aug 24 11:51 9992 -> socket:[547491750]


lrwx------ 1 root root 64 Aug 24 11:51 9993 -> socket:[547491752]


lrwx------ 1 root root 64 Aug 24 11:51 9994 -> socket:[547491753]


lrwx------ 1 root root 64 Aug 24 11:51 9995 -> socket:[547491754]


lrwx------ 1 root root 64 Aug 24 11:51 9996 -> socket:[547491755]


lrwx------ 1 root root 64 Aug 24 11:51 9997 -> socket:[547491756]


lrwx------ 1 root root 64 Aug 24 11:51 9998 -> socket:[547491757]


lrwx------ 1 root root 64 Aug 24 11:51 9999 -> socket:[547491758]


其实这个输出列表真的很长,只不过由于篇幅的原因,这里只粘贴上来了一小部分。从这个输出信息中,貌似一眼看不出来该程序占用的那些fd到底是在进行网络通信呢,还是在干嘛,于是我们可以用另一种方法:


lsof -p 16485
还是只展示一小部分输出信息:

java16485 root *500u IPv4 5475019090t0TCP abc.abc.com:57700->test1.abc.com:50010 (CLOSE_WAIT)


java16485 root *501u IPv4 5475019100t0TCP abc.abc.com:targus-getdata->test2.abc.com:50010 (CLOSE_WAIT)


java16485 root *502u IPv4 5475019110t0TCP abc.abc.com:59671->test3.abc.com:50010 (CLOSE_WAIT)


java16485 root *503u IPv4 5475019390t0TCP abc.abc.com:55784->test4.abc.com:50010 (CLOSE_WAIT)


java16485 root *504u IPv4 5475019420t0TCP abc.abc.com:netsupport->test5.abc.com:50010 (CLOSE_WAIT)


java16485 root *505u IPv4 5475019950t0TCP abc.abc.com:58486->test6.abc.com:50010 (CLOSE_WAIT)


java16485 root *506u IPv4 5475019960t0TCP abc.abc.com:38031->test7.abc.com:50010 (CLOSE_WAIT)


由于我这里的test*.abc.com是Hadoop集群的服务器,于是我马上就明白了:我的程序里有读写HDFS文件的操作,所以很可能是读写时没有close资源导致占用的fd持续增加。



[原创] 解决Linux系统上由于程序占用的文件描述符(file descriptor)过多导致的异常问题


微信扫一扫

第七城市微信公众平台