1. 程式人生 > >磁碟滿了,為啥du卻顯示還有很大空間?

磁碟滿了,為啥du卻顯示還有很大空間?

今天有個實習生問了我一個詭異的問題,“線下一臺磁碟大小32G的開發機(虛擬機器)打不出日誌”,把追查過程和大家分享一下。

畫外音:貴司開發機磁碟容量多大?

 

du一下,檢視磁碟空間:

[[email protected] ~]# du -sch /
16G     /

畫外音:似乎還有空間。

 

再試了一下df,發現結果不一樣:

[[email protected] ~]$ df -h
檔案系統        容量  已用 可用 已用%  掛載點
/dev/sda2      33G   33G   33G  100% /
/dev/sda1      965M   30M  886M   4% /boot

畫外音:顯示32G都用完了。

 

du:disk usage

通過搜尋檔案來計算每個檔案的大小然後累加得到的值。

 

df:disk free

通過檔案系統來獲取空間大小的資訊。

 

如果使用者刪除了一個正在執行的應用程式所開啟的某個目錄下的檔案:

  • du命令返回的值,顯示出減去了該檔案後的總大小

  • df命令返回的值,則不顯示減去該檔案後的大小(檔案控制代碼還在被使用),直到該執行的應用程式關閉了這個開啟的檔案(才會真正釋放空間)


常見的場景是,刪除了一個很大的正在寫入的tomcat的access日誌,du顯示的結果會把日誌大小減去,而df則仍會包含該日誌的大小(實際上tomcat仍引用了該檔案的控制代碼)。

 

對我們的啟示是,如果要刪除某個access日誌,不要粗暴的rm,而要溫柔的:

echo "" > access.log

畫外音:朋友們,有沒有rm過仍被引用的日誌?

 

如何發現被應用程式引用著“已刪除”檔案呢?

lsof:list open files

使用lsof檢視開啟的檔案。

 

lsof | grep deleted

結果顯示,一個我的logsvr程式(跑了幾個月了),和實習生寫的web-server程式(實習大作業)呈現deleted狀態,值得懷疑。

畫外音:請在手機上把圖放大。


最終定位出,是web-server程式中的一個:

while(pid=fork())

手誤寫成了:

while(pid==fork())

導致while內一直fork程序,直到將系統資源吃幹。並且該程序已經成了zombie程序,無法kill掉,重啟開發虛擬機器後,問題得到解決。

畫外音:我去,多了一個等號,這個bug好真實。

 

一分鐘不長,希望大家有收穫:

  • du:disk usage

  • df:disk free

  • lsof:list open files

  • echo "" > access.log