<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ##shell十三問之13: for what? while與until差在哪? ------------------------ 終于,來到了shell十三問的最后一問了... 長長吐一口氣~~~~ 最后要介紹的是shell script設計中常見的`循環`(`loop`). 所謂的`loop`就是script中的一段在一定條件下反復執行的代碼。 bash shell中常用的`loop`有如下三種: - for - while - until ###1. for loop -------------- `for` loop 是從一個清單列表中讀進變量的值, 并依次的循環執行`do`到`done`之間的命令行。 例: ```shell for var in one two three four five do echo ----------------- echo '$var is '$var echo done ``` > 上例的執行結果將會是: > 1. for會定義一個叫var的變量,其值依次是one two three four five。 > 2. 因為有5個變量值,因此,`do`與`done`之間的命令行會被循環執行5次。 > 3. 每次循環均用`echo`產生3個句子。而第二行中不在hard quote之內的$var會被替換。 > 4. 當最后一個變量值處理完畢,循環結束。 我們不難看出,在`for` loop中,變量值的多寡,決定循環的次數。 然而,變量在循環中是否使用則不一定,得視設計需求而定。 倘若`for` loop沒有使用in這個keyword來制變量清單的話,其值將從 `$@`(或`$*`)中繼承: ```shell for var; do ...... done ``` > **Tips:** > 若你忘記了`positional parameter, 請溫習第9章... `for` loop用于處理“清單”(list)項目非常方便, 其清單除了明確指定或從`postional parameter`取得之外, 也可以從`變量替換`或者`命令替換`取得... (再一次提醒:別忘了命令行的“重組”特性) 然而,對于一些“累計變化”的項目(整數的加減),for也能處理: ```shell for ((i = 1; i <= 10; i++)) do echo "num is $i" done ``` ###2. while loop --------- 除了`for` loop, 上面的例子, 我們也可改用`while` loop來做到: ```shell num=1 while [ "$num" -le 10 ]; do echo "num is $num" num=$(($num + 1)) done ``` `while` loop的原理與`for` loop稍有不同: 它不是逐次處理清單中的變量值, 而是取決于`while` 后面的命令行的return value: - 若為true, 則執行`do`與`done`之間的命令, 然后重新判斷`while`后的return value。 - 若為false,則不再執行`do`與`done`之間的命令而結束循環。 > 分析上例: > 1. 在`while`之前,定義變量num=1. > 2. 然后測試(`test`)$num是否小于或等于10. > 3. 結果為true,于是執行`echo`并將num的值加1. > 4. 再作第二輪測試,此時num的值為1+1=2,依然小于或等于10,因此,為true,循環繼續。 > 5. 直到num為10+1=11時,測試才會失敗...于是結束循環。 我們不難發現: **若`while`的測試結果永遠為true的話,那循環將一直永久執行下去**: ```shell while:; do echo looping... done ``` 上面的**`:`是bash的null command,不做任何動作, 除了返回true的return value**。 因此這個循環不會結束,稱作死循環。 死循環的產生有可能是故意設計的(如跑daemon), 也可能是設計的錯誤。 若要結束死循環,可通過signal來終止(如按下ctrl-c). (關于process與signal,等日后有機會再補充,十三問略過。) ####3.until loop ------- 一旦你能夠理解`while` loop的話,那就能理解`until` loop: **與`while`相反, `until`是在return value 為false時進入循環,否則,結束。 因此,前面的例子,我們也可以輕松的用`until`來寫: ```shell num=1 until [ ! "$num" -le 10 ]; do echo "num is $num" num=$(($num + 1)) done ``` 或者: ```shell num=1 until [ "$num" -gt 10 ]; do echo "num is $num" num=$(($num + 1)) done ``` okay, 關于bash的三個常用的loop暫時介紹到這里。 ###4. shell loop中的break與continue ------------------- 在結束本章之前,再跟大家補充兩個loop有關的命令: - `break` - `continue` 這兩個命令常用在復合式循環里, 也就是`do ... done`之間又有更進一層的loop, 當然,用在單一循環中也未嘗不可啦... ^_^ `break`用來中斷循環,也就是強迫結束循環。 若`break`后面指定一個數值n的話,則從里向外中斷第n個循環, 預設值為 `break 1`,也就是中斷當前循環。 在使用break時,需要注意的是,它與`return`及`exit`是不同的: - `break`是結束loop; - `return`是結束function; - `exit`是結束script/shell; 而`continue`則與`break`相反:強迫進入下一次循環動作. 若你理解不來的話,那你可簡單的看成: 在`continue`在`done`之間的句子略過而返回到循環的頂端... 與`break`相同的是:`continue`后面也可以指定一個數值n, 以決定繼續哪一層(從里往外計算)的循環, 預設值為 `continue 1`,也就是繼續當前的循環。 在shell script設計中,若能善用loop, 將能大幅度提高script在復雜條件下的處理能力。 請多加練習吧... --------------------- ## shell是十三問的總結語 ------------------------ 好了,該是到了結束的時候了。 婆婆媽媽地跟大家啰嗦了一堆shell的基礎概念。 目的不是要告訴大家“答案”,而是要帶給大家“啟發”... 在日后的關于shell的討論中,我或許經常用"連接"的方式 指引十三問中的內容。 以便我們在進行技術探討時,彼此能有一些討論的基礎, 而不至于各說各話、徒費時力。 但更希望十三問能帶給你更多的思考與樂趣, 至為重要的是通過實踐來加深理解。 是的,我很重視**實踐**與**獨立思考**這兩項學習要素。 若你能夠掌握其中的真諦,那請容我說聲: **恭喜十三問你沒白看了** ^_^ p.s. 至于補充問題部分,我暫時不寫了。 而是希望: 1. 大家補充題目。 2. 一起來寫心得。 Good luck and happy studing! -------------------------------- ##shell十三問原作者**`網中人`**簽名中的bash的fork bomb -------------- 最后,Markdown整理者補上本書的原作者**網中人**的個性簽名: > ** 君子博學而日叁省乎己,則知明而行無過矣。** > 一個能讓系統shell崩潰的shell 片段: ```shell :() { :|:& }; : # <--- 這個別亂跑!好奇會死人的! echo '十人|日一|十十o' | sed 's/.../&\n/g' # <--- 跟你講就不聽,再跑這個就好了... ``` 原來是一個bash的fork炸彈:ref:http://en.wikipedia.org/wiki/Fork_bomb 整理后的代碼: ```shell :() { :|:& } : ``` > 代碼分析: > (即除最后一行外) > 定義了一個 shell 函數,函數名是`:`, > 而這個函數體執行一個后臺命令`:|:` > 即冒號命令(或函數,下文會解釋)的輸出 通過管道再傳給冒號命令做輸入 >最后一行執行“:”命令 在各種shell中運行結果分析: > 這個代碼只有在 **bash** 中執行才會出現不斷創建進程而耗盡系統資源的嚴重后果; > 在 ksh (Korn shell), sh (Bourne shell)中并不會出現, > 在 ksh88 和傳統 unix Bourne shell 中冒號不能做函數名, > 即便是在 unix-center freebsd 系統中的 sh 和 pdksh(ksh93 手邊沒有,沒試)中冒號可以做函數名,但還是不會出現那個效果。 >原因是 sh、ksh 中內置命令的優先級高于函數,所以執行“:”, 總是執行內置命令“:”而不是剛才定義的那個恐怖函數。 > 但是在 **bash** 中就不一樣,bash 中函數的優先級高于內置命令, > 所以執行“:”結果會導致不斷的遞歸,而其中有管道操作, > 這就需要創建兩個子進程來實現,這樣就會不斷的創建進程而導致資源耗盡。 眾所周知,bash是一款極其強大的shell,提供了強大的交互與編程功能。 這樣的一款shell中自然不會缺少“函數”這個元素來幫助程序進行模塊化的高效開發與管理。 于是產生了由于其特殊的特性,bash擁有了fork炸彈。 Jaromil在2002年設計了最為精簡的一個fork炸彈的實現。 > 所謂fork炸彈是一種惡意程序,它的內部是一個不斷在fork進程的無限循環. > fork炸彈并不需要有特別的權限即可對系統造成破壞。 > fork炸彈實質是一個簡單的遞歸程序。 > 由于程序是遞歸的,如果沒有任何限制, > 這會導致這個簡單的程序迅速耗盡系統里面的所有資源.
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看