一、緣由:

最近看到這則新聞,很是悲傷,因為我最近也在用ansible;然而這一錯誤源自Ansible上糟糕的代碼設計,這款Linux實用工具被用於在多台不同服務器上自動執行腳本。
開發者解釋到,實際參數應該是“rm -rf {foo}/{bar}”,foo和bar是腳本中動態傳遞的兩個變量。然而由於變量處理出錯,通用語法未能成功在bash命令中插值,所以最終指令就變成了可怕的“rm -rf /”。
“rm -rf /”意味着擦除根路徑“/”下掛載的所有內容而無需詢問。
以前一個主管說過,在你不充分了解某個工具的原理的時候,不要太過相信依賴他。哪怕自己去寫個簡陋的,可以看到源碼,也是比較靠譜的。深信不疑!
二、解決辦法:
為了避免誤刪根目錄,或者重要的文件,整理了以下方法:
1、safe-rm
safe-rm 是一個開源軟件用來替代不太安全的rm,可以在/etc/safe-rm.conf中配置路徑黑名單,定義哪些不能被safe-rm刪除。
可以將 safe-rm 更名為 rm 並放在 $PATH 中比 原rm 程序靠前的位置。一些腳本中使用完全路徑/bin/rm則不會受此影響。
$ rm -rf /etc/ safe-rm: skipping /etc/
官方地址:http://freecode.com/projects/safe-rm,ubuntu可以直接apt-get安裝,centos要下載源碼安裝。
2、建立回收站機制
它並不真正執行刪除操作,而是將文件移動到一個特定目錄,可以設置定時清楚回收站,或者在回收站里面的文件大小達到一定容量時(或者用時間做判斷)執行刪除操作以騰出空間。
可以寫個shell腳本替換rm命令,或者在需要刪除文件的時候使用mv命令將文件移動到回收站。
1) 在/home/username/ 目錄下新建一個目錄,命名為:.trash
2)在/home/username/tools/目錄下,新建一個shell文件,命名為: remove.sh
TRASH_DIR="/home/username/.trash" for i in $*; do STAMP=`date +%s` fileName=`basename $i` mv $i $TRASH_DIR/$fileName.$STAMP done
3)修改~/.bashrc, 增加一行
alias rm="sh /home/username/tools/remove.sh"
用我們自建的remove.sh替代rm命令
4)設置crontab,定期清空垃圾箱,如:
0 0 * * * rm -rf /home/username/.trash/*
每天0點清空垃圾箱
5)source ~/.bashrc 使替換立即生效
3、注意腳本中rm -rf 變量的使用
在腳本盡量不要使用 rm -rf $FOO/, 請使用 rm -rf $FOO;另外刪除盡量不要寫相對路徑,不要帶變量。
4、根文件系統設置只讀掛載
noauto,ro
5、各種備份
可以異地遠程備份重要的數據,采用dump的增量備份機制,LVM快照,虛擬化環境中的快照、raid5等等。
附錄:How do I prevent accidental rm -rf /*?
