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

前两天在调查一个"too many open files"的问题,和之前一样,自然而然的用到了lsof,加上一堆漂亮的命令组合来查看哪些程序打开了很多文件。
lsof | awk '{print $2}' | uniq -c | sort -rnk1 | head
啪的一敲回车,很顺利的定位到几个docker内运行的Java进程排在最前,分别都是几万的结果,怀疑是不是docker的问题。很不幸的是,这个调查结果是错的。。。

先说真实的情况,后面再展开分析:

  • 真实的元凶,是一个并没有在上面的命令结果中排在最前面的进程,由于编程的bug,不断的打开同样的文件没有关闭,真正的占用了很多fd。
  • CentOS 7中的lsof是按PID/TID/file的组合显示结果的,上面lsof组合命令显示“打开”了很文件的进程,只是因为进程运行了N个线程,而每个线程都“用到”了M个jar包,并且FD一栏分别为mem和具体fd号都分别显示了一次,就出现了2*N*M——上万条结果。

结论一:
使用lsof查看fd数是不正确的。
尽管网上很多文章教人这么用,但实际上不应该这么做。

这是因为:

  1. lsof的结果包含了并非以fd形式打开的文件,比如用mmap方式访问文件(FD一栏显示为mem),实际并不占用fd。
    其中包括了像.so这样的文件。从结果看.jar文件也是以FD为mem和具体fd编号分别打开了一次。
  2. CentOS 7的lsof(我这里lsof -v的版本号是4.87)是按PID/TID/file的组合对应一行,不是一行一个fd。同一个进程如果多个线程访问同一个文件通常只需要打开一次、占用一个fd,但在lsof中就显示多行。
    如果用lsof -p <pid>,则不按TID显示,结果数少很多。但仍包含了没有使用fd的文件。

结论二:
准确的查看fd使用总数的命令是:
cat /proc/sys/fs/file-nr
或者(结果多的时候运行需要一段时间)
sudo find /proc -print | grep -P '/proc/\d+/fd/'| wc -l

注意如果用
sudo ls -l /proc/*/fd/* | wc -l
结果是不对的,比上面的命令返回结果少很多。原因是实际执行是会把*扩充成具体的目录作为参数,而这个参数长度有限制。

查看具体一个进程号的fd数量是:
ls -l /proc/<pid>/fd | wc -l

查看哪个进程使用的fd最多(再来一路组合拳):
sudo find /proc -print | grep -P '/proc/\d+/fd/'| awk -F '/' '{print $3}' | uniq -c | sort -rn | head

但还要注意上面的命令返回的是系统的fd使用情况,而ulimit的配置是针对单用户的,两者是有区别的。

结论三:
不同版本的lsof输出结果不同。

CentOS 7.3的lsof (我这里是4.87),按PID/TID/file显示。CentOS 6.6的lsof(我这里是4.82),按PID/file显示。结果数相差很大。但lsof -p <pid>的结果是一致的。
这在容器OS版本和宿主机OS版本不同时就需要注意了,在容器里和宿主机上用lsof查看同一进程的结果会很不同,我碰到的就是这种情况。

</br>


之前使用lsof(或lsof -n不解析协议主机名)的相关命令和真实意义:
打开文件总记录数(没太大意义):
lsof | wc -l

lsof -n | wc -l #不解析协议主机名

查看哪些pid使用文件数量最多(其实也没有太大意义):
lsof | awk '{print $2}' | uniq -c | sort -rnk1 | head



作者:petergz
链接:https://www.jianshu.com/p/407c2baef92e
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值