web-dev-qa-db-ja.com

並列プロセスを実行し、両方が終了したときに出力を組み合わせる方法

いくつかのデータを約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を同時に(たとえば、&を使用して)実行するにはどうすればよいですか?

どうも

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

17

waitを使用します。例えば:

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

意志:

  • data1パイプとData2パイプをバックグラウンドジョブとして実行する
  • 両方が完了するのを待ちます
  • analysisProgを実行します。

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

27
cxw

ファイルが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の詳細:

12
Ole Tange

これを行う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

このようにして、両方のパイプラインのバックグラウンドを設定し、実行が完了するまで待ってから、それらの出力を結合してstdinにします。これは、ヒアドキュメントで評価され、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
)

これらの概念については、以前に説明しました。おそらく最高のデモは herehere です。

1
mikeserv

これを使ってみてください。

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
0
Renan Vicente