使用 find 搭配 rm 刪除大量檔案

在一個風和日麗的夜晚,我坐在家裡看著電視,後來手機一陣響起,結果是楊老師發現一台主機發生異常,伺服器的 /var/spool/mqueue 目錄被塞了一堆還沒有寄出的信件,而當時沒有把 /var/spool 另外分割出來,所以也影響到了系統 root (/) 區塊,只剩六百多 MB 可以使用,這時一想會有幾個可能.

  1. 這台 server 有幫學校的 PC 做寄送信件,所以可能是廣告信在寄出.
  2. 使用這台 server 做 mail 寄信的機器,可能是中毒,於是就不斷的送信出去.

一開始只有想到這兩個原因,但是可要把被吞掉的空間給吐出來,所以就打算把所有的 mail queue 都先砍了,當然,要先停掉 mail service.

在砍這些正在排隊的信件時,發現一件事,就是裡面的檔案太多了,使用 ls 命令就變得超級遲頓,沒有反應,使用 mailq 來看看到底是那些信被 queue 住也沒辦法,後來想想算了,只好全剖砍了,不要再玩下去,之後,很順手的下了 rm -rf * 這下子呢,發生了一件很離奇的事,居然檔案太多無法刪除,第一次聽到 rm 在 complain (我是聽到的,楊老師是實作者,所以他有看到 ^^).

那個 error 是: bash: /bin/rm: Argument list too long

雖然無法刪除,但是楊兄並不放棄,到主機面前,開啟了 X Window 之後使用那 Linuxer 最常使用的鸚鵡螺 (nautilus) 開啟到 /var/spool/mqueue. 喔 ~ 可以使用 X Window 來刪呢 ! 後來想說即然 X Window 有這麼大的本事,那麼就用它來刪了其它的 queue files 就好啦,於是掛上電話,放楊兄一個人努力的在機房刪著 ...

當然我也沒有閒著,電視劇剛好演完,於是開啟我的工作伙伴,再度當網路潛水艇 ... 游著游著,突然想到,何不使用 find 來刪除看看 ? 於是刪回歷史文件,發現一個命令就是 find ./ | xargs rm -rf 千萬別小看這小小的指令,因為在我看完之後不久,楊兄打進來,說已經刪到手軟,這時也是晚上十點了,於是我就推薦了這個這道指令,嗯,很好,全都刪了,還頗快的 ...

喔,還沒說為什麼會刪到手軟,是因為 nautilus 在 Load 目錄時,是分批的,不是一次全部讀,所以一次大約是幾千封在讀,刪了之後,沒想到又冒出了還有幾千封 ... 真是嚇死人,後來推論應該是分批的關係.

在下了 find ./ | xargs rm -rf 之後,還在訝異快速之餘,就發現時間不多了,學校也要關門,所以就先 say bye bye,在現場苦命的楊兄也回家休息了.

分析:
rm 有最大一次刪除的數量,所以當一個目錄裡有太多的檔案或目錄時,就會出現錯誤,小弟試過應該是在二萬以下,而使用 find ./ | xargs rm -rf 的目的是先使用 find 列出檔案,再導向到 xargs,xargs 再喂給 rm,在這裡,xargs 會分批依照 rm 的最大數量餵給 rm,然後就可以順利刪除檔案了。而真正的原因,有可能是 rm 的版本或是檔案系統的問題,我也不再繼續追就,反正能辦好事就好 :)

下面提供當時小弟測試的一個小小 shell script

下載:mk-file.sh (這個 shell script 會有目錄下產生 20000 個檔案。)

接下來來做個小小測試:

root # mkfile.sh
root #

會產生 20000 個小檔案,名稱為 test-file-{1~19999}

直接使用 rm 去刪除:

root # rm -rf test-file-*
-bash: /bin/rm: Argument list too long (會回應引數過長的訊息)

改搭配 find 來刪除

root # find ./ -iname 'test-file-*' | xargs rm -rf
root # ls
mk-file.sh
root #

這樣就順利被刪除了。

06/21/2006


首頁