问题描述:

近日运维反馈我们项目组有两台sftp服务器句柄数过高,达到4.7万+,超过监控阈值4.5万。运维监控使用的命令如下:

cat /proc/sys/fs/file-nr
47008	0	6815744

原因分析:

我们常用的查询句柄的命令是lsof,结果与运维的命令相差很大(两种命令都需要root用户执行)。lsof结果如下:

lsof | wc -l
80311

查阅了部分资料,发现两个命令有一定关联,具体可以参考这两个博客:

Linux 文件句柄的这些技术内幕,只有 1% 的人知道

lsof的错误使用场景和查看打开文件数的正确方法

附上lsof命令结果详解:

lsof命令_Linux系统lsof命令详解

综合来讲,就是file-nr统计的是fd,即真正的文件句柄。lsof的结果包含了并非以fd形式打开的文件,比如用mmap方式访问文件(fd一栏显示为mem),实际并不占用fd。其中包括了像.so和.jar文件,也是以fd为mem和具体fd编号分别打开了一次。

虽然lsof的结果并不是真的句柄数,但是除去非fd形式的数量也能间接反映是什么原因导致的。因为服务器专门的sftp服务器,没有部署其他应用,所以我们需要知道每个用户占用了多少句柄数,于是再执行以下命令查看(结果中包含非fd的数量):

lsof -n | awk '{print $3}' | sort | uniq -c | sort -nr | head -4
46125 sftpuser1
33144 root
  369 sftpuser2
  369 sftpuser3

从结果可以看出,居然有用户比root使用的句柄数(结果均包含非fd的数量)还高,那大概率是这个用户连接sftp未释放导致的。


解决方案:


于是查看该用户连接sftp的代码,确实发现了有一处没有关闭链接,日积月累下来,则超过了告警阈值。

临时方案:重启对应的应用服务。重启后句柄数已经降下来了,执行命令:

cat /proc/sys/fs/file-nr
2080   0        6815744


最终方案:修改代码。。。

总结:

从这次事件来看,码农的任何一个不注意的点在日积月累后都可能造成蝴蝶效应,所以平时开发中还是要注重代码的质量,否则说不准哪天因为左脚先进办公室就被炒鱿鱼了。