如何運行並行進程並在兩個進程完成後合併輸出

如何運行並行進程並在兩個進程完成後合併輸出

我有一個 bash shell 腳本,其中我透過大約 5 或 6 個不同的程式傳輸一些數據,然後將最終結果放入製表符分隔的檔案中。

然後,我對一個單獨的相似資料集再次執行相同的操作,並將其輸出到第二個檔案。

然後將這兩個檔案輸入到另一個程式中進行比較分析。例如簡化

Data1 | this | that |theother | grep |sed | awk |whatever > Data1Res.csv
Data2 | this | that |theother | grep |sed | awk |whatever > Data2Res.csv
AnalysisProg -i Data1res.csv Data2res.csv

我的問題是:如何讓步驟 1 和步驟 2 同時運行(例如使用 &),但僅在兩者完成時啟動步驟 3(AnalysisProg)?

謝謝

ps AnalysisProg 不適用於流或 fifo。

答案1

使用wait。例如:

Data1 ... > Data1Res.csv &
Data2 ... > Data2Res.csv &
wait
AnalysisProg

將要:

  • 將 Data1 和 Data2 管線作為背景作業來執行
  • 等他們倆完成
  • 運行 AnalysisProg。

參見,例如,這個問題

答案2

如果你只有 2 個文件,cxw 的答案無疑是更好的解決方案。如果這 2 個文件只是範例,而您實際上有 10000 個文件,那麼「&」解決方案將不起作用,因為這會使您的伺服器超載。為此,您需要像 GNU Parallel 這樣的工具:

ls Data* | parallel 'cat {} | this | that |theother | grep |sed | awk |whatever > {}res.csv
AnalysisProg -i *res.csv

要了解有關 GNU Parallel 的更多資訊:

答案3

執行此操作的一種方法可能類似於:

AnalysisProg <<PREPROCESS /dev/stdin
$( 
{   process1=$( pipe | line | 1 >&2 & echo $! )
    process2=$( pipe | line | 2 >&2 & echo $! )
    while ps -p $process1 $process2 >/dev/null; do
        sleep 1
    done
} 2>&1
)
#END
PREPROCESS

透過這種方式,您可以將兩個管道設定為後台,但仍等待它們完成執行,然後再將它們的輸出合併到標準輸入中,該標準輸入在此處文件中進行評估並交給 AnalysisProg。如果你可以使用wait這甚至比while ps循環,但是,取決於外殼,wait如果您指示它等待某個進程,則可以反對不是目前 shell 的子級。

另請注意,上述方法將整理輸出 - 因此兩個進程將同時寫出。如果您希望將它們分開,或者將它們附加到另一個上,您可以這樣做:

AnalysisProg 3<<PREPROCESS /dev/fd/3 /dev/stderr
$(
process1=$(... >&2 ...) 2>/dev/fd/3
...
} 3>/dev/fd/3 2>/dev/stderr
)

我之前已經示範過這些概念。最好的演示可能是這裡這裡

答案4

嘗試使用這個。

rm -f Data1Res.csv
rm -f Data2Res.csv
Data1 | this | that |theother | grep |sed | awk |whatever > Data1Res.csv &
Data2 | this | that |theother | grep |sed | awk |whatever > Data2Res.csv &
while true
do
  ps aux | grep -v grep | grep -i -E 'Data1Res.csv|Data2Res.csv' &> /dev/null
  if [ $? -ne 0 ]
  then
    AnalysisProg -i Data1res.csv Data2res.csv
    exit 0
  fi
done

相關內容