Shell脚本经典之Fork炸弹
眾所周知,bash是一款極其強大的shell,提供了強大的交互與編程功能。這樣的一款shell中自然不會缺少“函數”這個元素來幫助程序進行模塊化的高效開發與管理。于是產生了由于其特殊的特性,bash擁有了fork×××。Jaromil在2002年設計了最為精簡的一個fork×××的實現。
所謂fork×××是一種惡意程序,它的內部是一個不斷在fork進程的無限循環,fork×××并不需要有特別的權限即可對系統造成破壞。fork炸 彈實質是一個簡單的遞歸程序。由于程序是遞歸的,如果沒有任何限制,這會導致這個簡單的程序迅速耗盡系統里面的所有資源。現在來看看Jaromil設計的 最簡單的fork×××:
:() { :|:& };:
或者
.() { .|.& };.
一行看似無法理解的只有13個字符的命令,即可占用掉所有系統的資源。其實,這行命令如果這樣寫成bash script就不難理解了:
:()
{
:|: &
}
;
:
*?第?1?行說明下面要定義一個函數,函數名為小數點,沒有可選參數。
*?第?2?行表示函數體開始。
*?第?3?行是函數體真正要做的事情,首先它遞歸調用本函數,然后利用管道調用一個新進程(它要做的事情也是遞歸調用本函數),并將其放到后臺執行。
*?第?4?行表示函數體結束。
*?第?5?行并不會執行什么操作,在命令行中用來分隔兩個命令用。從總體來看,它表明這段程序包含兩個部分,首先定義了一個函數,然后調用這個函數。
*?第?6?行表示調用本函數。
冒號”:”其實是函數名,這個bash腳本就是在不斷的執行該函數,然后不斷fork出新的進程。
對于函數名,大家可能會有所疑惑,小數點也能做函數名使用嗎?畢竟小數點是?shell?的一個內嵌命令,用來在當前?shell?環境中讀取指定 文件,并運行其中的命令。實際上的確可以,這取決于bash對命令的解釋順序。
默認情況下,bash處于非POSIX模式,此時對命令的解釋順序如下:
*?關鍵字,例如?if、for?等。
*?別名。別名不能與關鍵字相同,但是可以為關鍵字定義別名,例如?end=fi。
*?特 殊內嵌命令,例如?break、continue?等。POSIX?定義的特殊內嵌命令包括:.(小數點)、:(冒號)、break、continue、 eval、exec、exit、export、readonly、?return、set、shift、times、trap?和?unset。 bash?又增加了一個特殊的內嵌命令?source。
*?函數。如果處于非?POSIX?模式,bash?會優先匹配函數,然后再匹配內嵌命令。
*?非特殊內嵌命令,例如?cd、test?等。
*?腳本和可執行程序。在?PATH?環境變量指定的目錄中進行搜索,返回第一個匹配項。
由 于默認情況下,bash?處于非?POSIX?模式,因此fork×××中的小數點會優先當成一個函數進行匹配。(注:使用小數點代替其中的冒號,也能起到完全相同的效果。)
要使用POSIX模式來運行bash腳本,可以使用以下三種方法:
*?使用?–posix?選項啟動?bash。
*?在運行bash之后,執行?set?-o?posix?命令。
*?使用?/bin/sh?。
那么,有沒有辦法扼制這種情況的發生呢?答案是肯定的,只需設置進程的limit數即可。
[root@localhost?~]#?ulimit?-u?128
[root@localhost?~]#?ulimit?-a
core?file?size??????????(blocks,?-c)?0
data?seg?size???????????(kbytes,?-d)?unlimited
max?nice????????????????????????(-e)?20
file?size???????????????(blocks,?-f)?unlimited
pending?signals?????????????????(-i)?unlimited
max?locked?memory???????(kbytes,?-l)?unlimited
max?memory?size?????????(kbytes,?-m)?unlimited
open?files??????????????????????(-n)?1024
pipe?size????????????(512?bytes,?-p)?8
POSIX?message?queues?????(bytes,?-q)?unlimited
max?rt?priority?????????????????(-r)?unlimited
stack?size??????????????(kbytes,?-s)?8192
cpu?time???????????????(seconds,?-t)?unlimited
max?user?processes??????????????(-u)?128
virtual?memory??????????(kbytes,?-v)?unlimited
file?locks??????????????????????(-x)?unlimited
[root@localhost?~]#?.()?{?.|.&?}?;?.
[1]?6152
[root@localhost?~]#?bash:?fork:?Resource?temporarily?unavailable
bash:?fork:?Resource?temporarily?unavailable
bash:?fork:?Resource?temporarily?unavailable
…
在上面的例子中,我們將用戶可以創建的最大進程數限制為?128,執行fork×××會迅速fork出大量進程,此后會由于資源不足而無法繼續執行。使用工具ulimit即可設置各種限制數,具體的請參考該工具的man或help。
fork ×××讓我們認識到了遞歸函數的強大功能,同時也意識到一旦使用不當,遞歸函數所造成的破壞將是巨大的。實際上,fork?×××只是一個非常簡單的遞歸函 數,它并不涉及參數傳遞、返回值等問題,而這些問題在使用bash編程時是否有完善的支持呢?在bash中編寫遞歸函數時應該注意相關問題。
關于Fork×××的詳細資料請看:http://en.wikipedia.org/wiki/Fork_bomb
轉載于:https://blog.51cto.com/silencezone/1708349
總結
以上是生活随笔為你收集整理的Shell脚本经典之Fork炸弹的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java基础学习总结(42)——Log4
- 下一篇: 驱动继电器实验