在 Linux 上如何清理垃圾系統管理員
唔,感覺很有道理啊,你看,rm
是刪除,這個單詞簡單好記;連 rf
都給出了解釋,「垃圾文件」;/*
代表目錄下的所有文件,沒毛病;sudo
也有了,確保許可權沒問題。
哈哈,你一定會說,又編段子搞笑,沒人會信的。
會有人執行這樣的命令來清理所謂的垃圾文件么?你別說,這還真不好說。
我們經常會發一些關於關於 Bash 別名的文章,總有一些同學皮一下「貢獻」一些別緻的別名,比如 alias ls=rm -rf
,alias cd=rm -rf
等等。雖然我認為幾乎沒有人會被這些命令惡搞,但是大家也屢屢樂此不疲。
我將這張圖發到朋友圈裡,好友「龍十三」表示,這不僅僅清除垃圾文件,而且清除垃圾系統管理員。
是啊,為什麼會有這樣的段子一再出現呢?就是因為我們有些不求甚解的人,遇到問題了,習慣於從網上隨便找個命令示例瞎試,不去探究其原理,也不去核實可靠性。所以,這樣的段子真是用來清除「系統管理員里的垃圾」的。
那麼讓我們來探究一下上面這條命令,看看這裡有多少知識點。
rm 的那些事
首先,這條命令是用來清除 Linux 系統的根目錄(/
)下所有文件的。它使用了兩個命令選項:
-r
: 遞歸 ,對目錄及其下的內容進行遞歸操作-f
: 強制 ,無需確認操作
這兩個選項可以單獨寫作 -r
和 -f
,也可以按 POSIX 慣例,將兩個選項合併成 -rf
。這裡的 -r
和 -f
選項,絕非上圖中惡搞的 「Rubbish」 和 「Files」。
其後的參數 /*
指的是根目錄 /
下的所有文件。
-r 選項
-r
選項代表 遞歸 ,其意思是指遞歸地對參數中的目錄及其下的文件或子目錄進行刪除操作。
這個選項除了短選項風格,還有 GNU 風格的長選項 --recursive
;也出於兼容性的原因,支持同義的大寫 -R
參數。
如果沒有該選項,則不會刪除目錄及其下的內容。
-f 選項
在介紹 -f
選項之前,讓我們先看一下這裡沒有出現的 -i
選項。
原生的 rm
命令在刪除文件或目錄時,遵循 UNIX 慣例,在執行刪除操作前和操作成功後,是靜默的,毫無提示的。除非遇到錯誤(如要刪除的文件不存在)時,否則絕不抱怨。
後來,可能是鑒於很多人經常會錯誤刪除文件,在絕大多數的 Linux 發行版上的 rm
命令是一個添加了 -i
選項的別名:
alias rm=rm -i
這裡的 -i
選項用於在每一個刪除動作前做個提示,需要用戶明確給予確認才會刪除。
但是,有時候,這種提示實在是太煩了,所以,很多人在操作時,特意使用 -f
選項覆蓋了 -i
選項的行為,使得這個別名的定義毫無意義。
因此,還有一個 -I
選項,這個選項在要刪除三個及更多的文件或遞歸刪除時,會做一次確認提示。這樣,既沒有 -i
選項那麼煩人,又能防止大部分錯誤操作。所以,可以將上述別名採用 -I
選項,並避免使用 -f
選項。
* 通配了什麼
我們看到命令中以*
來指代目錄下的所有文件。但是嚴格來說,*
這個通配符代表不以點 「.
」 開頭的所有文件。以 「.
」 開頭的文件默認屬於 Linux 下的隱藏文件。
因此,這個命令不會刪除 /
目錄下以 .
開頭的隱藏文件,以及 .
和 ..
兩個目錄。但是在遞歸操作時,會遞歸地刪除子目錄下除了 .
和 ..
目錄之外的所以文件和子目錄——無論是否以 .
開頭——因為遞歸操作不是由 Bash 等 shell 進行通配展開的。
至於為什麼不在刪除目錄下的內容時也將 .
和 ..
一視同仁?因為自從 1979 年 rm
命令開始有刪除目錄的能力時,就專門避開了這兩個特殊目錄。
根目錄保護
有一定經驗的系統管理員可能這個時候會想起來,rm
命令有一對專門針對根目錄的選項 --preserve-root
和 --no-preserve-root
。這對選項的意思是:
--preserve-root
:保護根目錄,這是默認行為。--no-preserve-root
:不保護根目錄。
這對選項是後來添加到 rm
命令的。可能幾乎每個系統管理員都犯過操作錯誤,而這其中刪除過根目錄的比比皆是(我就是一個)。出現這種情況的原因有幾種:
- 輸入手誤:比如本來想輸入
rm /tmp/test.txt
,結果不小心鍵盤打的飛起,多輸入了一個空格變成:rm / tmp/test.txt
。看到根目錄(/
)後面的空格了么?!——這就是我當前自己親手犯過的錯誤,而且是在生產伺服器上。 - 未正確初始化或命名錯誤的 shell 腳本變數:比如在腳本中,
rm -rf /${tmp_dir}
,如果無論是tmp_dir
變數沒有正確賦值還是輸入錯誤(原本或許是tmpdir
?),那會導致什麼?當然是刪除根目錄咯~
鑒於這種情況層出不窮,在 Linux 圈子幾乎和「初學者如何退出 vi」 一樣成為經典笑話了。所以,在 POSIX 第七版規範中,rm
命令添加了 --preserve-root
選項,並將其作為默認行為,以降低出現這種錯誤的可能。
但是,這個選項不能防範本文中所述的清除根目錄下所有文件(/*
)的操作。
有的同學可能要問,那為什麼還會專門出現 --no-preserve-root
選項呢?這可能主要是出於 UNIX 哲學的考慮,給予你想要的一切權力,犯傻是你的事情,而不是操作系統的事情。萬一,你真的想刪除根目錄下的所有文件呢?
你還別說,真有這種需求:比如你要清除一個 chroot 環境下的所有文件。 chroot 我們這裡不多講,它就是以一個目錄作為「監獄」,該目錄在邏輯上形成了新的「根目錄」,在該監獄內的文件操作不能跨出該目錄範疇。近些年流行的 Docker、LXC/LXD 之類的容器技術,都是一種 chroot 技術。
UEFI 系統
好吧,你可能更特立獨行一些,就是要清除物理環境中的根目錄下所有文件!但是在你按下回車鍵之前,請再考慮一下,你是否在一個 UEFI 系統上?
因為 UEFI 系統會將其固件、變數和設置映射到根目錄下的 /sys
分區裡面,所以,如果在 UEFI 環境中清除根目錄下的所有內容,也會同樣清除 /sys
,這將可能會導致你丟失 UEFI 的固件設置,從而使設備變磚。
sudo 提權
為了可以刪除屬於 root 等系統和其它用戶的文件,這個命令還需要在前面加上 sudo
來提權。
輸入該命令後,會要求輸入密碼。誰的密碼?不是 root 密碼,而是輸入該命令的當前用戶的密碼。
而對於誰能執行 sudo
命令,以及他可以通過 sudo
命令執行什麼命令等知識點,這裡就不再贅述,請參閱我們的其它文章。順便說一句,要記得區分 sudo
和 su
命令的聯繫與區別。
垃圾文件
研究到這裡,我們不能忘記這條命令原本的意圖,刪除「垃圾文件」。
Linux 下有垃圾文件么?有。這些垃圾文件一般來源於:
- 沒有被包管理器管理的孤兒文件,在軟體包被刪除後,遺留在系統中
- 無用的依賴包,在需要這些依賴包的軟體被刪除後,沒有相應刪除
- 沒有清理的臨時文件
- 遺留的診斷文件
那麼這些垃圾文件需要清除么?一般而言,Linux 系統上的這些文件大多不會對系統的健康運行造成任何影響,除非太多了,佔據了很多存儲空間和 inode。
所以,如果你感覺你的 Linux 系統慢了,那幾乎可以肯定不是由於垃圾文件導致的,至少在這一點上,來自 Windows 系統的經驗並不值得複製。
好了,關於這個簡單的命令,我們已經挖掘了這麼多知識點,你都知道了嗎?
事實上,關於這些知識,還有更多的內涵、外延和歷史信息,作為一個真正的系統管理員,而不是一個腳本小子,需要認真地研究每個命令和細節。
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive