主要記錄一下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值特別大的時候,我們應該控制併發進程的個數,不然會影響系統其他進程的運行,甚至死機。
那麼如何控制進程的數量?
在網上參考了一下別人的方法,主要都是利用管道的思想。
參考如下程序:
#!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個字符串,然後每從管道內讀出一個字符串就生成一個子進程,當管道內沒有字符串可讀時就阻塞在那裏,不能創建新的子進程,一直等到有新的字符串進來時才繼續運行。當每個併發進程執行完畢時又向管道內寫入一個字符串,表示當前子進程已執行完畢,可以創建新的子進程了。
轉自:Shell腳本中的併發