“bash: fork: Resource temporarily unavailable”的解決方案

這兩天,我登陸到一臺服務器上,偶爾就出現”bash: fork: Resource temporarily unavailable”的提示,這是什麼命令都不能用,但偶爾過一會就好了。前兩天也沒太在意,今天再次遇到,然後找到了根本原因。
當出現”bash: fork: Resource temporarily unavailable”時,一般來說是系統上的進程數量太多了,達到了命令”ulimit -u”的限制。(當系統進程達到限制後,kernel會自動kill掉一些進程,這就是好我過一會又能操作的原因了。)這種情況產生的原因,一是某個程序有bug,不斷地fork新的進程消耗系統資源,二是可能中了病毒(惡意程序),比如所謂的fork炸彈。

我進行了如下操作:

[repo@vt-sync jay]$ ulimit  -u
1024
[repo@vt-sync jay]$ ps -ef | wc -l
1221
[repo@vt-sync jay]$ ps ux | wc -l
1020

發現當前用戶下面居然有1020個進程,我仔細一看,很多的”vgt-sync.sh”之類的進程,這個shell腳本是我自己以前寫的啊,裏面有一個while的死循環,本來單獨運行這個腳本是正確的,沒有任何問題,但是我卻把它配置到crontab任務中每小時都去運行,這樣就會每小時都會新增一個vgt-sync.sh進程,隨着時間的推移,本機上的進程就越來越多了,從而導致了上面的問題。

所以,我的找到原因,解決方法就簡單了,顯示kill掉這些進程,然後修改我的腳本,既然用了crontab就別寫死循環了。

[repo@vt-sync jay]$ ps ux | wc -l
1020
[repo@vt-sync jay]$ killall vgt-sync.sh
#(wait for several seconds.)
[repo@vt-sync jay]$ ps ux | wc -l
12

再來看看我的那個非常簡單腳本吧,剛好和crontab結合起來使用就有了bug了。

#! /bin/bash
set -x
linux_dir="/home/repo/pub/linux-vgt.git/"
xen_dir="/home/repo/pub/xen-vgt.git/"
while [ 1 ]
do
        cd $linux_dir
        git pull
        cd $xen_dir
        git pull
        sleep 30
done

我遇到的情況是自己的程序bug,下面簡單說一下fork炸彈吧。
所謂fork炸彈是一種惡意程序,它的內部是一個不斷在fork進程的無限循環,fork炸彈並不需要有特別的權限即可對系統造成破壞。現在來看一個最簡單的fork炸彈:

 :() { :|:& };:

一行看似無法理解的只有13個字符的命令,即可佔用掉所有系統的資源。其實,這行命令如果這樣寫成bash script就不難理解了:

:()
{
    :|: &
}
;
:

冒號”:”其實是函數名,這個bash腳本就是在不斷的執行該函數,然後不斷fork出新的進程。那麼,有沒有辦法扼制這種情況的發生呢?答案是肯定的,只需設置進程的limit數即可,就算fork炸彈運行也沒關係,如果我的limit限制很小的話,幾百個簡單進程也不消耗完系統的所有資源:
ulimit -u 200 #設置當前用戶最多的進程數量限制爲200

  使用工具ulimit即可設置各種限制數,具體的請參考該工具的manual page(man bash)。在這裏筆者限制了max user processes數爲200,所以,可以安全地執行這個fork炸彈了:

[repo@vt-sync jay]$ :() { :|:& };:
[1] 9593
[repo@vt-sync jay]$ bash: fork: Resource temporarily unavailable
bash: fork: Resource temporarily unavailable
bash: fork: Resource temporarily unavailable
bash: fork: Resource temporarily unavailable


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章