歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> SHELL編程 >> linux bash Shell腳本經典之Fork炸彈解析:() { :|:& };:

linux bash Shell腳本經典之Fork炸彈解析:() { :|:& };:

日期:2017/3/1 15:53:07   编辑:SHELL編程
linux bash 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中編寫遞歸函數時應該注意相關問題。
Copyright © Linux教程網 All Rights Reserved