1. 程式人生 > 其它 >033df和du顯示的磁碟空間使用情況不一致的原因及處理

033df和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的使用情況
  1. [root@centos192 testdu]# df -h /dev/sda1  
  2. 檔案系統          容量  已用  可用 已用%% 掛載點  
  3. /dev/sda1              49G  776M   45G   2% /var  
(2)新建一個1GB的大檔案
  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結果:
  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結果:
  1. [root@centos192 var]# du -sh /var/  
  2. 1.6G    /var/  
此時兩者結果基本相同。   (4)模擬一個程序開啟這個大檔案,然後刪除這個大檔案
  1. [root@centos192 var]# tail -f myfile.iso &  
  2. [1] 23277  
  3. [root@centos192 var]# rm -f myfile.iso   
  (5)此時,再對比du和df的結果 首先確認有程序持有myfile.iso控制代碼。
  1. [root@centos192 var]# lsof | grep myfile.iso  
  2. tail      23955      root    3r      REG                8,1 1048576000       7999 /var/myfile.iso (deleted)  
  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控制代碼。
  1. [root@centos192 var]# lsof | grep myfile.iso  
  2. [root@centos192 var]#   
  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返回的值才顯示出減去了該檔案後的檔案系統的使用情況。