6万个小文件撑爆了Inode,我在周五下班前差点崩溃

admin 2026-05-20 04:52:53 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文档记录了一次磁盘空间报警的应急处理过程,运维人员发现Java微服务因部署脚本缺陷频繁重启,在/tmp目录下累积了6万多个hsperfdata小文件,导致磁盘空间和inode同时耗尽。通过删除残留文件、修复脚本循环重启问题、添加定期清理任务解决。关键教训是排查存储问题时应优先使用df-i命令快速识别小文件耗尽inode的情况。 综合评分: 91 文章分类: 应急响应,实战经验,安全运营,终端安全,其他


cover_image

6万个小文件撑爆了Inode,我在周五下班前差点崩溃

原创

刘军军 刘军军

运维星火燎原

2026年5月20日 00:00 山西

在小说阅读器读本章

去阅读

下午4:50,监控报警,磁盘96%。

那台机器是跑一个 Java 微服务的,业务量不大但比较关键。我一边 ssh 一边想,多半又是哪个同事把大文件丢 /tmp 忘了删。

[root@euler-app01 ~]# df -h
文件系统        容量  已用  可用 已用% 挂载点
/dev/vda1        98G   94G  4.0G   96% /

还真是。我赶紧敲 du 看看到底谁最占空间:

[root@euler-app01 ~]# du -sh /* 2>/dev/null | sort -rh | head -10
3.6G    /usr
2.3G    /var
1.9G    /home
1.2G    /opt
988M    /root
...

这几个加起来也就 10G 左右,跟 94G 完全对不上。我又试了一遍 du -sh /,这次不加过滤,结果一样:

[root@euler-app01 ~]# du -sh /
3.6G    /usr
2.3G    /var
...

明显不对。我心想,难道是有进程占着已删除文件没释放?这种情况用 lsof 能查出来。

[root@euler-app01 ~]# lsof | grep deleted | head -20
java    27341  root   12w   REG  253,0  20971520  123456 /app/logs/error.log (deleted)
java    27341  root   13w   REG  253,0  10485760  123457 /app/logs/access.log (deleted)
java    27342  root   12w   REG  253,0  15728640  123458 /app/logs/error.log (deleted)
...

确实有不少。我直接把这几个 Java 进程重启了一下:

[root@euler-app01 ~]# systemctl restart app-service
[root@euler-app01 ~]# lsof | grep deleted | wc -l
12

还剩一些,但已经少了很多。再看 df -h:

[root@euler-app01 ~]# df -h
/dev/vda1        98G   78G   20G   80% /

降到了 78G,还有接近 70G 不知所踪。这就奇怪了——lsof 释放了大概 16G,但离最初的 94G 还差一大截。

我怀疑是不是 /proc 或者某些挂载点下面的内容被 du 忽略了。又试了 du -sh --exclude=/proc --exclude=/sys /,结果几乎没有变化。

这时候天已经黑了,办公室就剩我一个人。我有点烦躁,重新敲了一遍 du -sh /* 2>/dev/null | sort -rh,这次没有 head,而是让结果全部输出。我一行一行往下翻,翻到快最后的时候,突然看见一行:

67G     /tmp

第一次跑的时候 /tmp 这行被挤到第 23 行,我根本没看到。

赶紧进去看看:

[root@euler-app01 ~]# cd /tmp
[root@euler-app01 tmp]# ls -la | head -20
total 24
drwxrwxrwt  9 root root  4096 May 19 17:32 .
drwxr-xr-x 19 root root  4096 Mar 10  2024 ..
drwxr-xr-x  2 root root  4096 May 19 16:01 hsperfdata_root_27341
drwxr-xr-x  2 root root  4096 May 19 16:02 hsperfdata_root_27342
drwxr-xr-x  2 root root  4096 May 19 16:03 hsperfdata_root_27343
...

全是 hsperfdata 开头的目录。数一下有多少:

[root@euler-app01 tmp]# ls -d hsperfdata_* | wc -l
64321

六万多个目录。每个目录里基本都有一个几 KB 的文件:

[root@euler-app01 tmp]# ls -l hsperfdata_root_27341/
total 8
-rw------- 1 root root 4096 May 19 16:01 27341

文件不大,但架不住数量多。这时候我突然想到一个命令——df -i,看 inode 的。

[root@euler-app01 tmp]# df -i
文件系统        Inodes 已用(I) 可用(I) 已用(I)% 挂载点
/dev/vda1       6.4M    6.3M    0.1M       98% /

果然,inode 也快用完了。磁盘空间被这些小文件撑满,同时 inode 也被耗尽,两个指标都爆了。

至于为什么会生成这么多 hsperfdata,后来查了历史,是因为那个 Java 服务的部署脚本有个 bug,每两小时会检测一次健康状态,检测失败就重启。每次重启都会在 /tmp 下新建一个 hsperfdata 目录,但是退出时没有正确清理。跑了几个月,就堆了六万多个。

恢复业务很简单,直接删:

[root@euler-app01 tmp]# rm -rf hsperfdata_*
[root@euler-app01 tmp]# df -h && df -i
/dev/vda1        98G   31G   67G   32% /
/dev/vda1       6.4M   1.2M  5.2M   19% /

然后我改了两处:一是修了部署脚本,不让它频繁重启;二是在 crontab 里加了一周清理一次 /tmp/hsperfdata_* 的任务。

后来跟同事复盘,我说这次最大的失误就是一开始没看 df -i。要是早几分钟敲这个命令,看到 inode 满了,就能立刻想到是小文件的问题,不会在 du 的输出里翻来翻去找半天。这个教训估计我能记好几年。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:运维星火燎原 刘军军 刘军军《6万个小文件撑爆了Inode,我在周五下班前差点崩溃》

评论:0   参与:  0