1. 程式人生 > >Shell指令碼中的併發(1)

Shell指令碼中的併發(1)

主要記錄一下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個字串,然後每從管道內讀出一個字串就生成一個子程序,當管道內沒有字串可讀時就阻塞在那裡,不能建立新的子程序,一直等到有新的字串進來時才繼續執行。當每個併發程序執行完畢時又向管道內寫入一個字串,表示當前子程序已執行完畢,可以建立新的子程序了。