主要記錄一下Shell腳本中的命令的並發和串行執行。
默認的情況下,Shell腳本中的命令是串行執行的,必須等到前一條命令執行完后才執行接下來的命令,但是如果我有一大批的的命令需要執行,而且互相又沒有影響的情況下(有影響的話就比較復雜了),那么就要使用命令的並發執行了。
看下面的代碼:
- #!/bin/bash
- for(( i = 0; i < ${count}; i++ ))
- do
- commands1
- done
- commands2
對於上面的代碼,因為每個commands1都挺耗時的,所以打算使用並發編程,這樣就可以節省大量時間了。
修改后的代碼如下:
- #!/bin/bash
- for(( i = 0; i < ${count}; i++ ))
- do
- {
- commands1
- }&
- done
- commands2
這樣的話commands1就可以並行執行了。 實質是將commands1作為后台進程在執行,這樣主進程就不用等待前面的命令執行完畢之后才開始執行接下來的命令。
但是我的本來目的是讓commands1的這個循環都執行結束后,再用command2去處理前面的結果。如果像上面這樣寫的話,在commands1都還沒結束時就已經開始執行commands2了,得到了錯誤的結果。
再次修改代碼如下:
- #!/bin/bash
- for(( i = 0; i < ${count}; i++ ))
- do
- {
- commands1
- }&
- done
- wait
- commands2
上面這樣就可以達到預期的目的了,先是所有的commands1在后台並行執行,等到循環里面的命令都結束之后才執行接下來的commands2。
對於上面的代碼,如果count值特別大的時候,我們應該控制並發進程的個數,不然會影響系統其他進程的運行,甚至死機。
上篇主要是寫的如何在Shell腳本中編寫並發程序,這次寫一下如何控制進程的數量。
在網上參考了一下別人的方法,主要都是利用管道的思想。
參考如下程序:
- #!bin/bash
- PRONUM=10 #進程個數
- tmpfile="$$.fifo" #臨時生成管道文件
- mkfifo $tmpfile
- exec 6<>$tmpfile
- rm $tmpfile
- for(( i=0; i<$PRONUM; i++ ))
- do
- echo "init."
- done >&6
- for(( i = 0; i < ${count}; i++ ))
- do
- read line
- #echo $line
- {
- commands
- echo "line${i} finished."
- } >&6 &
- done <&6
- wait
初始時給管道內寫入PRONUM個字符串,然后每從管道內讀出一個字符串就生成一個子進程,當管道內沒有字符串可讀時就阻塞在那里,不能創建新的子進程,一直等到有新的字符串進來時才繼續運行。當每個並發進程執行完畢時又向管道內寫入一個字符串,表示當前子進程已執行完畢,可以創建新的子進程了。