df与du下的磁盘空间不一致

     本来是定好了的学习目标,一年又过去了,速度慢如蜗牛,各种事情接踵而至,哎!还来得及,只要努力就有希望。这几天读鸟哥的那本书,目前进展在文件系统那块,好些理论性的东西还是不太了解,在各处查阅资料翻到一篇文章讲df与du命令查找结果不一致的问题,正好与我不谋而合,特此转来以作日后参考。

      我们在Nagios中设置了Linux各分区可用空间超过90%就邮件报警。一次报警发生后,开发人员进行处理,发现依然在报。我们看下状况:

[root@CH36 home]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda5             1.3T  811G  394G  68% /
tmpfs                  24G   88K   24G   1% /dev/shm
/dev/sda1             2.0G   61M  1.8G   4% /boot
/dev/sda3             9.7G  8.8G  846M  92% /home

报警的是/home分区,可用空间只有846M了。我们再看下/home下哪个目录比较大:

[root@CH36 home]# du -sh *
751M    xxx
32K     ganglia
72K     hadoop
16K     lost+found
1.5G    abc
44K     mysql
60K     d
3.7M    server
32K     e

奇怪的事情发生了,这些目录大小合计才2G多,应该有7G左右可用才对,为什么df与du的输出矛盾呢?

考察一下du与df这两个命令。

1.du命令

du -sh命令通过将指定文件系统路径下所有的目录、符号链接、文件使用的块数累加起来得到总块数以及总大小。它会遍历这个目录,针对所有真实存在的文件、目录等汇总,给出最终结果。所以,通过du -sh给出的已使用空间情况,肯定是真实的!

2.df命令

df命令常被用来检查分区空间使用情况。它与du不同,它是查看文件系统磁盘块分配图得出总块数与剩余块数。

文件系统分配一些磁盘块用来记录它自身的一些数据,如i节点,磁盘分布图,间接块,超级块等。这些称为MetaData,对于用户级程序如du是不可见的。而df命令则查看磁盘分配图并考虑MetaData。

描述还是比较抽象,我们看下Linux下写一个文件的后台操作:

  1. 首先,获取这个文件的文件句柄,这是会判断这个文件是否存在!

  2. 然后,程序所有的写入操作仅仅使用文件句柄,而不再关注具体文件是否存在!Linux中允许对一个正在写入的文件进行删除RM或者移动MV,而Windows中是不允许这样的操作的。

可能会有这样的疑问了:

文件都删除了,应用程序还在写入,写到哪里去了呢?

其实应用程序获取句柄,就直接指向到了磁盘位置,到了数据块的级别上进行写入了,不再检查数据块所属的文件是否存在。这时候的写入,对于其他人,由于访问的入口�C文件�C不存在了,所以是看不到其写入的内容的!

解决方案

了解了du和df的基本原理,再看我们的这个问题,基本可以确认,du的结果是真实的使用情况,而开发人员的处理方式可能是直接删除RM了大文件。先验证一下这个猜测:

通过ps查到java应用程序的pid为12136,我们看看它所持有的文件句柄中有哪些异常:
[root@CH36 home]# ls -l /proc/12136/fd | grep -i deleted
l-wx―― 1 xxx xxx 64 Jan  8 10:40 1 -> /home/xxx/nohup.out (deleted)
l-wx―― 1 xxx xxx 64 Jan  8 10:40 2 -> /home/xxx/nohup.out (deleted)
l-wx―― 1 xxx xxx 64 Jan  8 10:40 97 -> /home/xxx/log.log.5 (deleted)

再查看这些文件,都不存在。事实上,即使存在同名文件,也可能是删除后新生成的,与句柄原始对应的不是同一个文件了。

与开发人员确认后,事实就是如此。重启Java应用后,df能够看到与du中查看到的已使用空间相一致!

正确的清空文件的方式是执行shell命令”> file.txt“。

其他:调整ext4的预留空间大小百分比

在开始检查问题时,还误入歧途,认为可能是ext4文件系统保留空间的问题。也记录于此吧。

ext3和ext4文件系统有一个特点,默认每个分区保留5%的空间,不允许非root用户使用。我们应该这部分空间的存在,或者什么时候可以救个急。

1.查看ext4分区的预留空间

shell> dumpe2fs /dev/sda5 | grep ‘Reserved block count’
dumpe2fs 1.41.12 (17-May-2010)
Reserved block count:     16893926

块大小为4k,则这个分区保留了64G,确实是总量1.3T的5%。

2.设置预留空间百分比

[root@CH36 home]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda5             1.3T  812G  394G  68% /
tmpfs                  24G   88K   24G   1% /dev/shm
/dev/sda1             2.0G   61M  1.8G   4% /boot
/dev/sda3             9.7G  2.7G  7.0G  28% /home

[root@CH36 home]# tune2fs -m 0 /dev/sda5
tune2fs 1.41.12 (17-May-2010)
Setting reserved blocks percentage to 0% (0 blocks)

[root@CH36 home]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/sda5             1.3T  812G  458G  64% /
tmpfs                  24G   88K   24G   1% /dev/shm
/dev/sda1             2.0G   61M  1.8G   4% /boot
/dev/sda3             9.7G  2.7G  7.0G  28% /home

可以看到,调整后,可用空间增加了64G!

博客原址:http://ju.outofmemory.cn/entry/72026

你可能感兴趣的:(linux,开发,文章,空间,学习目标)