
確切地說,我的 tmpfs /tmp 使用 RAM,2GB。通常,這已經足夠了,但有時,進程會在其中建立文件並且無法自行清理。如果它們崩潰了,就會發生這種情況。我需要刪除這些孤立的 tmp 文件,否則將來的進程將耗盡 /tmp 上的空間。
如何安全地進行垃圾收集/tmp?有些人透過檢查上次修改時間戳來做到這一點,但這種方法是不安全的,因為可能存在長時間運行的進程仍然需要這些檔案。更安全的方法是將上次修改時間戳條件與沒有程序擁有該文件的文件句柄的條件結合。是否有一個程式/腳本/等體現了這種方法或其他一些也安全的方法?
順便說一句,Linux/Unix 是否允許一種透過建立開啟檔案的模式,其中建立的檔案在建立進程終止時被刪除,即使是因為崩潰?
答案1
你可能會想嘗試這樣的事情:
find /tmp -mtime +7 -and -not -exec fuser -s {} ';' -and -exec echo {} ';'
find 用於尋找符合特定條件的文件。
-mtime +7
僅選擇超過 7 天的檔案(您可以使用任何其他值)-exec fuser -s {} ';'
對於每個符合舊度標準的文件,以靜默模式呼叫 fusionr。 fusionr 對於目前已存取的每個檔案傳回 0 (=true),而未存取的檔案則傳回 1 (= false)。由於我們只對未訪問的感興趣,因此我們-not
在其前面放了一個-exec
-exec echo {} ';'
僅列印符合條件的所有檔案名稱。您可能想-exec rm {} ';'
在此處使用 use ,但由於這可能會刪除一些仍在使用的文件,因此我認為首先執行簡單的 echo 更安全。- 編輯:您可能需要新增類似
-name 'foo*.bar'
或的內容-uid 123
來限制清理對特定檔案模式或使用者 ID 的影響,以避免意外影響。
最後一點:考慮到可能存在只寫入一次(例如在系統啟動時)但頻繁讀取(例如任何 X-session-cookie)的檔案。因此,我建議添加一些名稱檢查,以僅影響由錯誤程式建立的檔案。
編輯2: 對於你的最後一個問題:除非沒有進程擁有開啟的句柄,否則檔案不會從磁碟中刪除(至少對於本機 Linux 檔案系統而言)。問題是目錄條目被立即刪除,這意味著從刪除檔案時起,沒有新進程可以再開啟該檔案(因為沒有附加檔案名稱)。
詳情請參閱: https://stackoverflow.com/questions/3181641/how-can-i-delete-a-file-upon-its-close-in-c-on-linux
編輯3:但如果我想自動化整個流程怎麼辦?
正如我所說,可能存在寫入一次然後每隔一段時間讀取一次的檔案(例如 X 會話 cookie、PID 檔案等)。這些不會被這個小刪除腳本排除(這就是為什麼您可能想在echo
實際刪除檔案之前先進行測試運行的原因)。
實現安全解決方案的一種方法是使用atime
.
atime
儲存每個文件上次存取的時間。但是該檔案系統選項經常被停用,因為它對效能有相當大的影響(根據這個部落格大約在 20-30% 的區域)。有relatime
,但是那個只在mtime
更改時寫入訪問時間,所以這個對我們沒有幫助。
如果你想使用atime
,我建議/tmp
在一個單獨的分割區(最好是虛擬磁碟)上使用,這樣對整個系統的效能影響不會太大。
啟用後atime
,您只需將-mtime
上述命令列中的參數替換為-atime
.
您也許可以刪除-not -exec fuser -s {} ';'
,但我將其保留在那裡只是為了確定(以防應用程式長時間打開文件)。
echo
但請記住,在最終刪除系統仍然需要的內容之前,請先測試使用的命令!
答案2
不要自己卷。
Debian/Ubuntu 有 tmpreaper,它可能在其他發行版中也可用。
# tmpreaper - cleans up files in directories based on their age
sudo apt-get install tmpreaper
cat /etc/tmpreaper.conf
答案3
答案4
取得早於 so 的文件列表,排除由該列表中的任何內容開啟的文件:
find /tmp -mtime +7 |\
egrep -v "`lsof -n +D /tmp | awk 'NR>1 {print $9}'| tr \\n \|`"
lsof -n +D /tmp
:在 /tmp 中尋找開啟的檔案
awk 'NR>1 {print $9}'
:僅列印 lsof 輸出的第九列,不包括標題
tr \\n \|
:用 bar 取代換行符號(或在egrep中)
egrep -v "foo|moo|bar"
:列印不包含 foo 或 moo 或 bar 的行