情景
有天看到有開發(fā)同事A在討論群里說,一測試環(huán)境中某服務打印了大量的日志,把磁盤打滿了。這位同事把日志清理了,并請群里的相關人員看下是否需要重啟各自的服務。過一會兒,同事B說其中一服務雖然重新啟動了,但并未正常啟動,因為啟動日志中依然顯示著... No space left on device ...。
前有同事A說磁盤滿并把日志清了,后有同事說磁盤還是沒有剩余空間。這前后矛盾的現(xiàn)象,激起了我的興趣,于是我登錄到該測試環(huán)境服務器上一探究竟。
分析
BTW:
上述所說服務的路徑均在/opt目錄下,產(chǎn)生的文件也都在/opt目錄的相關子目錄下。所以,下面示例中關注/opt路徑的磁盤空間即可。
使用df命令查看:
df -lh
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/cl-root 92G 12G 80G 13% /
devtmpfs 7.8G 0 7.8G 0% /dev
tmpfs 7.8G 0 7.8G 0% /dev/shm
tmpfs 7.8G 75M 7.7G 1% /run
tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
/dev/sda1 1014M 138M 877M 14% /boot
/dev/mapper/vg_data2-lv_data2 200G 200G 20K 100% /opt
在/opt目錄下使用du命令查看:
sudo du -h --max-depth=1
6.4M ./blueset
9.7G ./lanxin
16K ./mysqlback
86M ./logs
9.8G .
由上可知:
du命令得到/opt目錄只占用了9.8G的空間,而df命令則顯示200G全部被占滿。為什么會這樣呢?du和df得到的磁盤占用的數(shù)值不應該一致的么?
原理
經(jīng)過一番搜索,發(fā)現(xiàn)了df和du的差別:
- 正常情況下,兩者的輸出其實也并不完全相同,但只是稍有差異;
du命令得到的是將指定文件系統(tǒng)中所有的目錄、符號鏈接和文件使用的塊數(shù)累加,即該文件系統(tǒng)使用的總塊數(shù);
df命令得到的是文件系統(tǒng)磁盤塊分配情況,包括總塊數(shù)、剩余塊數(shù)等。
文件系統(tǒng)分配其中的一些磁盤塊用來記錄它自身的一些數(shù)據(jù),如inode,磁盤分布圖,間接塊,超級塊等。這些數(shù)據(jù)對大多數(shù)用戶級的程序來說是不可見的,通常稱為Meta Data(元數(shù)據(jù))。
du命令是用戶級的程序,它不考慮Meta Data,而df命令則查看文件系統(tǒng)的磁盤分配圖并考慮Meta Data。
因此正常情況下,df計算的USED空間會比du計算的結果要稍大些。
- 特殊情況下,兩者輸出的結果差異很大;
上述碰到的問題就是這種特殊情況。
du是以文件名、目錄名等為依據(jù)計算空間使用的,而df是以硬盤塊使用情況來計算空間使用的。
當一個應用程序正在寫一個大文件的時候,雖然我們可以對這個文件進行刪除或挪走,但應用程序依然占有著句柄,并根據(jù)句柄所指磁盤位置直接寫磁盤,而不檢查該文件是否存在。
對應到上面的場景中,服務在向日志文件中寫入時,因為磁盤空間不足,所以把日志文件刪除了。但由于服務并沒有停止,所以它還占用著句柄,因而兩者得到的數(shù)據(jù)也不一樣。
解決方案
對于當前存在的df和du結果不一致問題,可選的解決方案有:
1 重新掛載這個分區(qū);
2 將未關閉的服務停掉,釋放句柄;
如果在一開始A同事發(fā)現(xiàn)磁盤空間不足時,應該怎么做?
應清空日志文件的內容(echo ' ' > server.log),而不是直接刪除文件。通過這種方法,磁盤空間可以立即釋放,進程可以繼續(xù)向文件寫入日志,而不必重啟服務。
如果日志文件內容需要保留,可以先復制一份保存起來,再清空原文件。
相關鏈接
http://itindex.net/detail/39369-linux-df-du
http://www.chinaunix.net/old_jh/6/465673.html
該帖中摘要了一篇來自2001年發(fā)布的網(wǎng)文片段,對du和df區(qū)別的介紹很詳細,推薦仔細閱讀。