並列プロセスを実行し、両方のプロセスが完了した後に出力をマージする方法

並列プロセスを実行し、両方のプロセスが完了した後に出力をマージする方法

私は約5〜6つの異なるプログラムを介していくつかのデータをパイプし、最終結果をタブ区切りのファイルに保存するbashシェルスクリプトを持っています。

その後、別の同様のデータセットで同じ操作を再度実行し、それを2番目のファイルに出力します。

両方のファイルは比較分析のために別のプログラムに入力されます。たとえば、単純化

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(AnalyticProg)を開始するにはどうすればよいですか?

ありがとう

ps AnalysisProgはストリームまたはfifoでは機能しません。

答え1

使用wait。たとえば、

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

する:

  • Data1およびData2パイプラインをバックグラウンドジョブとして実行する
  • 両方が終わるまで待ってください。
  • AnalysisProgを実行します。

たとえば、次を参照してください。この問題

答え2

ファイルが2つしかない場合、cxwの答えは確かにより良い解決策です。この2つのファイルは単なる例であり、実際に10,000個のファイルがある場合、「&」ソリューションはサーバーに過負荷を引き起こすため、機能しません。これにはGNU Parallelなどのツールが必要です。

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

GNUパラレルの詳細については:

  • 簡単な紹介については、紹介ビデオをご覧ください。 https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
  • このチュートリアル(manparallel_tutorial)を見つけてください。あなたのコマンドラインがあなたを愛するでしょう。

答え3

これを行う1つの方法は次のとおりです。

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一部のプロセスを待つように指示すると、異議を申し立てることができます。現在、シェルの子ではありません。

また、上記の方法は出力を照合するため、両方のプロセスが同時に記録されます。それらを分離または互いに追加するには、次の手順を実行します。

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

関連情報