網站上傳失敗,訊息說「No space left on device」,但df看起來還有容量。先不要刪一批不認識的檔案:可能是inode已用完,也可能看錯了檔案系統。另一種情況是檔案已刪,空間卻遲遲不回來,因為程序仍把它開著。
這兩種問題的查法不同。inode不足會讓新檔案無法建立,即使資料區還有容量;已刪開啟檔則可能讓目錄裡看不到的內容,仍佔著檔案系統空間。先把寫入位置、容量、inode與開啟檔對上,再決定處理方式。
查真正寫入的那個路徑
不要只看根目錄的df。網站上傳、暫存、備份與日誌可能在不同掛載點,出錯的是暫存目錄,網站素材目錄卻還有空間。把命令中的路徑換成實際失敗位置,先做唯讀查詢:
df -h /實際寫入目錄
df -i /實際寫入目錄
第一行看資料區容量,第二行看inode使用量。記下Filesystem、掛載點、可用容量與IFree,不要只抄最後的百分比。容器裡的路徑可能是獨立volume或tmpfs,也可能落在容器可寫層;主機和容器看到的結果需要按實際掛載對照。
空檔案也需要inode
大量零位元組的小檔案,幾乎不佔資料容量,仍需要檔案系統的識別資源。除了普通檔案,目錄也會使用inode。若IFree是0,建立新檔可能失敗;不能因檔案都很小,就認為它們沒有影響。
本文用專用容器的1MiB tmpfs重現,明確限制16個inode。起初根目錄使用1個,建立15個空檔後,df仍顯示1024KiB可用,inode卻已16/16,第16個檔案建立失敗。
容量:1024 KiB,可用 1024 KiB
inode:16 個,已用 16 個,可用 0 個
touch: No space left on device
清掉這15個專用測試檔後,inode回到已用1個、可用15個。這說明容量和inode是不同限制;例子是受限tmpfs,不能把它的inode設定方法直接搬到ext4或其他正式檔案系統。
找到小檔來源,才安排清理
若inode確實耗盡,先核對哪個應用持續產生暫存、快取或工作檔。大量失敗重試、沒有到期清理的快取與堆積佇列,都可能留下許多小檔,但不能只憑目錄名稱叫cache就直接刪掉。
有GNU du的環境,可用inode統計比較目標目錄的子層:
du --inodes -x --max-depth=1 /要核對的目錄
這是GNU選項,BusyBox或其他版本未必相同。查之前先看當地工具手冊;大型目錄的掃描也會花時間與I/O,限定相關位置,不要一開始遞迴全機。權限不足或掃描中資料變動,也會影響結果。
清理應按應用的保留與到期規則,由負責人確認檔案用途、備份與恢復方式。只刪已確認可丟棄的資料,並處理持續產生檔案的原因;不然暫時空出inode,很快又會塞滿。
如果問題是幾十萬個小檔,刪掉一個很大的備份,可能釋放大量容量,卻只多出很少inode。反過來,清掉許多零位元組檔案,容量數字可能幾乎不變,inode卻明顯恢復。處理目標要和耗盡的資源一致。
同一個inode也可能有多個硬連結名稱,所以檔名數不一定等於inode數。不要把find數出的行數直接當成df -i的總用量;目錄結構、硬連結與工具統計範圍都要一起看。
刪掉名稱,程序還可能把檔案開著
Linux移除檔案名稱後,若仍有程序開啟該檔,內容可以繼續存在。直到指向它的最後一個檔案描述符關閉,且沒有其他硬連結保留名稱,空間才有條件釋放。
本文另建立512KiB檔案,讓同一個測試shell用描述符3保持開啟。移除檔名後,du在目錄裡看到0KiB,但df仍顯示已用512KiB,描述符指向的路徑帶有deleted。關閉這個描述符後,df才回到已用0KiB。
階段 df 已用 du 目錄用量
檔案存在且開啟 512 KiB 512 KiB
檔名移除、仍開啟 512 KiB 0 KiB
最後描述符關閉 0 KiB 0 KiB
用lsof找仍被持有的已刪檔
在已有lsof且具備查看權限的Linux環境,先查連結數少於1的開啟檔:
lsof +L1
核對程序名稱、PID、檔案描述符、裝置與檔名,確認它屬於哪個檔案系統和服務。不要看到deleted就結束所有程序;有些程式正常使用匿名或已移除的暫存檔,是否異常還要看持有大小與生命週期。
查不到也不等於沒有開啟檔。工具是否存在、查看權限、程序命名空間與容器隔離,都可能限制你看到的範圍。交維護者時保留必要欄位,避免公開私人路徑或客戶資料。
讓服務正常釋放,不要盲目砍程序
若確認某服務持有已刪的大日誌,按它的官方輪替與重新開啟日誌流程處理。不同服務的重新載入方式不同,不能把一個訊號當成所有程式通用命令。需要重新啟動時,也先確認業務影響和恢復安排。
不要直接對陌生PID使用kill -9,也不要把/proc裡的描述符當成可以任意清空的檔案。這可能破壞正在寫入的資料;找到持有者,是為了交給正確的服務流程釋放。
同一個檔案可能被多個描述符或程序持有。關掉其中一個,不代表最後一個也已關閉;若用量沒有下降,重新核對剩餘持有者,而不是重複刪那個已經不存在的名稱。服務是否會重新開啟同名日誌,也要另行確認。
df與du不同,不只這一個原因
du計算的是走訪到的目錄內容,df看的是檔案系統統計。掛載點、權限、硬連結、保留空間與掃描期間的資料變化,都可能讓兩者不同。先用相同檔案系統和明確範圍比較,不能看到數字不一致就認定一定有已刪開啟檔。
容量和inode都有餘量,寫入仍失敗時,另外查完整錯誤、唯讀掛載、權限、配額與應用限制。先縮小是哪一層拒絕寫入,不必把每個問題都塞進「硬碟滿了」。
處理後,用同一個寫入位置重新查df與df -i,再完成一個已授權的小型寫入驗證。記下釋放了哪一類資源、由哪個服務處理,並確認檔案沒有繼續無限制增長。數字下降只證明資源變化,網站上傳或備份是否恢復仍要按具體功能核對。
參考資料
GNU coreutils du手冊:目錄用量與inode統計
Linux unlink:已刪但仍開啟的檔案
Linux tmpfs:容量與inode限制
lsof官方手冊:+L連結數選擇

評論0