linux磁盘磁盘,du和df命令的结果不一样

图片说明

如图,du命令显示根目录有24G,但是df命令又说根目录有31G,使用量已经超过了80%
服务器监控一直告警,这个误差究竟怎么产生的呢?

另外,服务器有装docker

du 显示的是所有可以遍历目录找到的文件的大小总和,df 显示的是磁盘实际的占用空间。
这两个不同的话,一般是因为删除了某个已经被其他进程打开的文件,这种文件空间被回收的话需要等到那个进程关闭文件或退出。

解决办法:
1. 以root身份执行命令:lsof -p | grep deleted
2. 从上面命令打印出来的输出结果里,第一列是进程ID,第二列是已经被删除但未关闭的文件
3. ps aux | grep 进程ID 把相应的进程找出来,重启那个进程就可以释放空间,进程没啥用的话直接 kill 掉也行

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

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

du是通过stat命令来统计每个文件(包括子目录)的空间占用总和。因为会对每个涉及到的文件使用stat命令,所以:
1. 如果统计目录下挂载了其他文件系统,那么也会对这个文件系统进行统计。例如"du -sh /"的时候,统计了所有分区的文件,包括挂载上来的。
2. 如果文件被删除,但却被其他进程引用了。由于它"不存在"于文件系统上,stat命令无法对其统计,所以这样的文件不会统计。
3. 可以跨分区统计某些你想统计的文件大小总和。因为它们都能被stat统计。

df则是读取每个分区的superblock来获取大小,因此速度极快(superblock才占用1024字节)。
当我们删除一个文件的时候,会将这个文件对应的inode记录中指向data block的指针删除,并将标记这个文件占用数据库的bit map标记为0,同时在它的父目录里将这个文件的记录删除。
每当文件被删除,文件系统通过bit map能立刻知道每个块组中哪些数据块是空闲的,哪些数据块是被使用的,这些信息都更新在superblock中。而df则根据这些数据块的数量,计算出有多少空闲空间,多少已使用空间。
因此:
(1).当某个文件系统下挂载了其他分区,则不会把这个分区也统计进去。
(2).当文件被删除,但有某个进程引用了这些数据时,由于这些数据对应的bit map还没有标记为0(但是inode指针和父目录中的记录已经删除了,
所以du以及其他任何命令都找不到它),superblock的信息还不会被更新,df计算的结果中当然还包含这些数据占用的空间。
(3).df对文件系统中的某个文件进行统计时,会自动转为统计这个文件系统的信息。因为它读取的是superblock。