问题背景:
现网环境出现磁盘告警,df -h 查看/var占用了9.4G,du -sh * 查看实际只占用了1.8G,lsof /var |grep deleted查看也没有未释放的文件句柄,重启服务器也无法恢复。
排查思路:
分别使用man df 和 man du 可以查看到两个命令的区别
df:report file system disk space usage,报告文件系统的中磁盘使用的空间。数据来源于文件系统中的元数据信息。当文件被删除,但是还有进程在使用,文件句柄没有被释放时,df也会统计进去。
du:estimate file space usage,统计文件的空间大小。数据来源于基于文件路径去统计的每个目录文件的大小。当文件被删除,即使因为还有进程在使用导致文件句柄没有释放,du也会因为找不到文件路径,而无法统计该文件的大小。
在该案例中,使用lsof查询了,并没有被标记为delete但还没有被释放的文件句柄,所以需要根据df和du的区别,来列举场景,一一排查:
1 目录下面有隐藏的文件和目录,被设置了特殊权限,以致于du无法访问到它们
2 文件系统错误,从而导致df统计结果错误
排查过程:
1 客户环境使用的是xfs的文件系统,该文件系统常出现的问题是磁盘碎片,所以使用xfs_db检测/var 对应分区的碎片情况
发现存在71.72%的碎片
2 使用xfs_fsr进行清理,出现了报错
该报错是因为没有足够的空间来为ino分别为8390242 8390233 16800098 这几个大文件进行磁盘碎片的整理了
3 使用xfs_db来调试获取对应ino对应的磁盘块,也会报错
所以判断文件系统的元数据信息有所损坏
4 使用xfs_check来检测文件系统的元数据信息,如果有错误会尝试自动修复,报错了,报错原因是因为该文件系统还处于挂载状态,无法修复
修复方案
由于/var属于root目录,存在许多跟系统相关的程序,无法在系统运行时umount,所以需要在grub菜单中添加文件系统修复的系统启动命令,进行修复。具体操作如下:
vim /etc/default/grub
找到GRUB_CMDLINE_LINUX参数,并在行尾附加fsck.mode=force fsck.repair=yes
执行grub2-mkconfig
然后重启 reboot
发现df -h 已经统计正确了
总结:
该问题排查的难点是:
- 了解df和du的原理,才能提供排查文件系统的思路
- 连接grub系统启动配置,才能提供“在grub配置中修复根目录的文件系统”的解决方案
另外注意df的统计性能比du的性能更高哦,希望大家了解原理之后,可以更好的应用到实际场景中去。
最后给大家分享一下自己整理的不同文件系统的调试命令: