S_lion's Studio

df与du结果不一致问题

字数统计: 1k阅读时长: 3 min
2021/08/03 Share

dfdu命令都是运维人员常用的检测存储空间大小的命令,平时我们并不太关注这两个命令的差别,但是经常会遇到这样一种场景,使用df查看到空间使用率已经非常高了,但使用du命令排查时发现不存在占用空间大的文件, 两者间的结果不一致。

du与df

du,disk usage,是通过搜索文件来计算每个文件的大小然后累加,du能看到的文件只是一些当前存在的,没有被删除的。他计算的大小就是当前他认为存在的所有文件大小的累加和。

df,disk free,通过文件系统来快速获取空间大小的信息,当我们删除一个文件的时候,这个文件不是马上就在文件系统当中消失了,而是暂时消失了,当所有程序都不用时,才会根据OS的规则释放掉已经删除的文件, df记录的是通过文件系统获取到的文件的大小,他比du强的地方就是能够看到已经删除的文件,而且计算大小的时候,把这一部分的空间也加上了,更精确了。

因此,如果用户删除了一个正在运行的应用所打开的某个目录下的文件,则du命令返回的值显示出减去了该文件后的目录的大小。但df命令并不显示减去该文件后的大小。直到该运行的应用关闭了这个打开的文件,df返回的值才显示出减去了该文件后的文件系统的使用情况。

通过lsof工具我们可以直观的排查到具体的问题进程,以便解决:

模拟案例

分别创建一个500M和1000M大小的文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ dd if=/dev/zero of=500mFile bs=1M count=500
记录了500+0 的读入
记录了500+0 的写出
524288000字节(524 MB)已复制,1.34728 秒,389 MB/秒
$ dd if=/dev/zero of=1000mFile bs=1M count=1000
记录了1000+0 的读入
记录了1000+0 的写出
1048576000字节(1.0 GB)已复制,13.3469 秒,78.6 MB/秒
$ du -ha *
1000M 1000mFile
500M 500mFile
$ df -h `pwd`
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root 18G 4.0G 15G 22% /

然后开两个终端分别使用tail命令查看。

1
2
3
4
# 终端1执行
$ tail -f 500mFile
# 终端2执行
$ tail -f 1000mFile

再开启一个终端使用lsof命令查看这两个文件的状态。

1
2
3
4
$ lsof |grep File
tail 10105 root 3r REG 253,0 524288000 51733031 /home/slions/500mFile
tail 10106 root 3r REG 253,0 1048576000 51738061 /home/slions/1000mFile

这个时候我们使用rm命令来删除了这两个文件。

1
2
3
4
5
6
$ rm -rf 1000mFile 500mFile
$ du -ha .
0 .
$ df -h `pwd`
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root 18G 4.0G 15G 22% /

可以看到du已经显示为0,df无任何变化。通过lsof再看下进程状态。(sort -nrk 7是进行大小排序)

1
2
3
4
$ lsof |grep File |sort -nrk 7
tail 10106 root 3r REG 253,0 1048576000 51738061 /home/slions/1000mFile (deleted)
tail 10105 root 3r REG 253,0 524288000 51733031 /home/slions/500mFile (deleted)

这个deleted表示该已经删除了的文件,但是文件句柄未释放。

想要释放此句柄直接kill掉对应进程就好了。

1
2
3
4
5
6
$ kill -9 10106
$ kill -9 10105
$ df -h `pwd`
文件系统 容量 已用 可用 已用% 挂载点
/dev/mapper/centos-root 18G 2.5G 16G 14% /

可以看到,df的已用容量对应减少了1.5G。

在日常的运维工作中,我们可以直接通过以下命令来快速定位未释放文件句柄的进程,从而进行解决。

1
$ lsof |grep deleted

建议

在日常运维过程中,如果我们需要删除比较大的文件 可以使用 > filename ,这种可以直接释放磁盘空间,使用 rm 如果有进程在访问文件,则有可能出现磁盘空间不释放的情况。

CATALOG
  1. 1. du与df
  2. 2. 模拟案例
  3. 3. 建议