Linux下du命令和df命令读取的磁盘占用不一致问题

道锋潜鳞
2022-07-23 / 1 评论 / 56 阅读 / 正在检测是否收录...

前引

前几天,站长随手打开了本站的后台,宝塔面板
有接近一个月没有登陆控制面板,寻思着日志占用应该也非常大了
然后站长就看到了如下场景

l5x47vk3.png

50G的系统盘占用达到了69%
(其实之前是85%,后来清理日志文件后降低到69%)
然后发现不管怎么清理日志或者是其他的垃圾文件,空间占用就是没法降低。
因此习惯性的连上ssh

df -hl

结果和宝塔显示的大同小异
l5x4br6j.png
同样也是占用69%
ps:这其实很正常,宝塔面板和df命令读取的都是磁盘的superblock信息,数据相同也无可厚非。

但是问题就在这来了,站长不信邪,不相信系统盘占用有这么高。因为本站的服务器挂载有两块数据盘,一块800G,一块4T,站点日志和站点数据,面板都安装在数据盘上,理论上不应该会占用系统盘的空间啊。

于是使用

cd /
du -sh * | sort -n
du -h -x --max-depth=1

去直接计算根目录下所有目录的大小

l5x4kip3.png

好家伙,除去挂载点的大小,实际系统根目录占用仅仅5.5G,根本不到69%
这是什么情况呢

解决

错误的想法

细心的网友可能会注意到,如果这5.5G,加上www挂载点的15G,加上data挂载点的0.7G
5.5+15+0.7,大概21.2G左右,加上前面的tmpfs空间,正好大概33G
事情会不会这么巧呢,还真是巧合而已。

解析

区别

前面有说,宝塔面板和df命令读取的都是磁盘分区的 superblock 信息。
du 命令则是一个个调用系统的 fstat 去统计文件的总大小
所以,理论上 df 统计的是更准确的
那这么说,为什么 df 统计的结果会和 du 差那么多呢。
是因为 df 统计的时候是从文件系统考虑的,不仅仅计算了文件的大小,也计算了被删除的文件,但进程还没释放的部分。

例如文件已经被删除,但是被某个进程持有。其原理是读取每个分区的superblock来获取空闲数据块、已使用数据块.从而计算出空闲空间和已使用空间,所以也因此导致df统计的速度极快(才占用1024字节)。

那df是怎么统计删除的文件的呢
简单说一下,只要bmap中不将这个文件的data block标记为未使用,就会算到实际使用的空间中。bmap是元数据区的一个位标记,其中记录的是数据区的block是否被使用。

解决

那我被占用的空间去哪了
这是个好问题,但是在这之前,站长需要发一个提醒


1.要找到这些丢失的空间,我们得首先先找到这些僵尸文件
使用

cd /
lsof |grep deleted

可以找到已经被表为deleted的文件被什么进程占用
然后可以使用kill批量结束进程。

cd /
lsof |grep -i delete|awk '{print $2}'|xargs kill

到这,基本上就能解决大部分问题了
站长的系统盘占用也恢复了
l5x4kip3.png

1

评论 (1)

取消
  1. 头像
    淄博漏水检测
    Windows 10 · Google Chrome

    感谢分享,赞一个

    回复