df和du顯示的磁盤空間使用情況不一致的原因及處理


 

在Linux下查看磁盤空間使用情況,最常使用的就是du和df了。然而兩者還是有很大區別的,有時候其輸出結果甚至非常懸殊。

1. 如何記憶這兩個命令

du-Disk Usage

df-Disk Free

2. df 和du 的工作原理

2.1 du的工作原理

du命令會對待統計文件逐個調用fstat這個系統調用,獲取文件大小。它的數據是基於文件獲取的,所以有很大的靈活性,不一定非要針對一個分區,可以跨越多個分區操作。如果針對的目錄中文件很多,du速度就會很慢了。

2.2 df的工作原理

df命令使用的事statfs這個系統調用,直接讀取分區的超級塊信息獲取分區使用情況。它的數據是基於分區元數據的,所以只能針對整個分區。由於df直接讀取超級塊,所以運行速度不受文件多少影響。

3 du和df不一致情況模擬

常見的df和du不一致情況就是文件刪除的問題。當一個文件被刪除后,在文件系統 目錄中已經不可見了,所以du就不會再統計它了。然而如果此時還有運行的進程持有這個已經被刪除了的文件的句柄,那么這個文件就不會真正在磁盤中被刪除, 分區超級塊中的信息也就不會更改。這樣df仍舊會統計這個被刪除了的文件。
(1)當前分區sda1的使用情況
[plain] view plain copy
  1. [root@centos192 testdu]# df -h /dev/sda1  
  2. 文件系統          容量  已用  可用 已用%% 掛載點  
  3. /dev/sda1              49G  776M   45G   2% /var  
(2)新建一個1GB的大文件
[plain] view plain copy
  1. [root@centos192 var]# dd if=/dev/zero of=myfile.iso bs=1024k count=1000  
  2. 記錄了1000+0 的讀入  
  3. 記錄了1000+0 的寫出  
  4. 1048576000字節(1.0 GB)已復制,24.0954 秒,43.5 MB/秒  
(3)此時的分區sda1使用情況
df結果:
[plain] view plain copy
  1. [root@centos192 var]# df -h /dev/sda1  
  2. 文件系統<span style="white-space:pre">  </span>      容量  已用  可用 已用%% 掛載點  
  3. /dev/sda1              49G  1.8G   44G   4% /var  
du結果:
[plain] view plain copy
  1. [root@centos192 var]# du -sh /var/  
  2. 1.6G    /var/  
此時兩者結果基本相同。

(4)模擬一個進程打開這個大文件,然后刪除這個大文件
[plain] view plain copy
  1. [root@centos192 var]# tail -f myfile.iso &  
  2. [1] 23277  
  3. [root@centos192 var]# rm -f myfile.iso   

(5)此時,再對比du和df的結果
首先確認有進程持有myfile.iso句柄。
[plain] view plain copy
  1. [root@centos192 var]# lsof | grep myfile.iso  
  2. tail      23955      root    3r      REG                8,1 1048576000       7999 /var/myfile.iso (deleted)  

[plain] view plain copy
  1. [root@centos192 var]# du -sh /var/  
  2. 596M    /var/  
  3. [root@centos192 var]# df -h /dev/sda1  
  4. 文件系統          容量  已用  可用 已用%% 掛載點  
  5. /dev/sda1              49G  1.8G   44G   4% /var  
可以看出,df結果沒有變化,而du則不再統計被刪除了的文件myfile.iso。

(6)停止模擬進程,再對比du和df結果
首先確認沒有進程持有myfile.iso句柄。
[plain] view plain copy
  1. [root@centos192 var]# lsof | grep myfile.iso  
  2. [root@centos192 var]#   

[plain] view plain copy
  1. [root@centos192 var]# du -sh /var/; df -h /dev/sda1  
  2. 596M    /var/  
  3. 文件系統          容量  已用  可用 已用%% 掛載點  
  4. /dev/sda1              49G  776M   45G   2% /var  
此時,myfile.iso已經沒有進程占有它了,也就從磁盤上刪除了,分區的超級塊信息已經更改,df也就顯示正常了。

4 工作中需要注意的地方

(1)當出現du和df差距很大的情況時,考慮是否是有刪除文件未完成造成的,方法是lsof命令,然后停止相關進程即可。
(2)可以使用清空文件的方式來代替刪除文件,方式是:echo > myfile.iso。
(3)對於經常發生刪除問題的日志文件,以改名、清空、刪除的順序操作。
(4)除了rm外,有些命令會間接的刪除文件,如gzip命令完成后會刪除原來的文件,為了避免刪除問題,壓縮前先確認沒有進程打開該文件。

 
du和df命令都被用於獲得文件系統大小的信息:df用於報告文件系統的總塊數及剩余塊數,du -s /<filesystem>用於報告文件系統使用的塊數。但是,我們可以發現從df命令算出的文件系統使用塊數的值與通過du命令得出的值是不一致的。如下例:
# du -s /tmp 返回如下值:
12920 /tmp
而 df /tmp返回如下值:
Filesystem 512-blocks Free %Used Iused %Iused Mounted on

/dev/hd3 57344 42208 26% 391 4% /tmp
 
從上面的值我們可以算出<total from df> - <Free from df> = <used block count>: 57344 - 42208 = 15136. 而15136大於12920。該值差異的存在是由於du與df命令實施上的不同: du -s命令通過將指定文件系統中所有的目錄、符號鏈接和文件使用的塊數累加得到該文件系統使用的總塊數;而df命令通過查看文件系統磁盤塊分配圖得出總塊數與剩余塊數。文件系統分配其中的一些磁盤塊用來記錄它自身的一些數據,如i節點,磁盤分布圖,間接塊,超級塊等。這些數據對大多數用
戶級的程序來說是不可見的,通常稱為Meta Data。 
du命令是用戶級的程序,它不考慮Meta Data,而df命令則查看文件系統的磁盤分配圖並考慮Meta Data。df命令獲得真正的文件系統數據,而du命令只查看文件系統的部分情況。例如,一個frag=4096 並且 nbpi=4096的空的大小為4MB的日志文件系統
中Meta Data 的分配情況如下:
1 4k block for the LVM
2 4k super blocks
2 4k blocks for disk maps
2 4k blocks for inode maps
2 4k blocks for .indirect
32 4k blocks for inodes

-------------------------
41 4k blocks for meta data on an empty 4MB file system
 
對於AIX 4.X 版本:
執行 du /foo返回的結果如下:
8 /foo/lost+found
16 /foo
要使du命令輸出的結果與df 命令輸出的結果匹配,我們必須要加上Meta Data。首先,將41個4k 的塊轉換為以512字節為單
位的值:
41 * 8 = 328
328(meta data) + 16(from du) = 344
所以有344個以512字節為單位的塊分配給了這個空的文件系統。
 
而使用 df /foo命令我們可以得到下面的結果:
Filesystem 512-blocks Free %Used Iused %Iused Mounted on
/dev/lv01 8192 7848 5% 16 2% /foo

從中我們可以得到該文件系統使用的塊數:8192(total blocks) - 7848(free blocks) = 344。該值與上面得出的值一致。
 


上面的換算方法對於空的文件系統很容易實現,但是對於非空的文件系統,由於Meta Data中文件間接塊的大小不定,因此較難實現。所以我們不需要查看du 與 df返回的值的匹配關系,而只需要了解du -s命令返回的值反映了分配給文件及目錄的磁盤塊數,而df命令則反映了文件系統的實際分配情況。df命令反映的實際情況包含了用戶數據(文件及目錄)和Meta Data。
 
另一個表現出du與df命令不同之處的例子如下:
如果用戶刪除了一個正在運行的應用所打開的某個目錄下的文件,則du命令返回的值顯示出減去了該文件后的目錄的大小。但df命令並不顯示減去該文件后的大小。直到該運行的應用關閉了這個打開的文件,df返回的值才顯示出減去了該文件后的文件系統的使用情況。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM