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


17

いくつかのデータを約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

私の質問は次のとおりです。step1とstep2を同時に(たとえば&を使用して)実行し、両方が完了したときにstep3(AnalysisProg)のみを起動するにはどうすればよいですか。

THX

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



ところで、Perlスクリプトを使用しても大丈夫ですか?これにより、問題が大幅に簡素化され、この後処理を非常に効率的に実装し、簡単に並列実行できます。
Bichoy

Perl ..あまりない、ない:(
スティーブンヘンダーソン14年

1
ここでtee、パイプ間で入力を分割し、2つの同時grepプロセスで処理する方法を示します。unix.stackexchange.com
120333

そして、ここで私は完全にバックグラウンドに通行中のプロセスの単純なシェル構造物の使用方法を示すnohupかもしれないが、それでもプロセスとの通信手段を維持:unix.stackexchange.com/questions/121253/...
mikeserv

回答:


27

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

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

意志:

  • Data1およびData2パイプをバックグラウンドジョブとして実行する
  • 両方が終了するのを待ちます
  • AnalysisProgを実行します。

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


Thx、それはよさそうだ。上記が機能しない場合は、これを試してみます。
スティーブンヘンダーソン14年

THXは再び、私は一種の待機の意識のだったが、少しググたが、それが今、私はそれだけで「待機」であることがわかり異なるPIDなど。私の感触をばかに働いていたかに混乱していた
スティーブン・ヘンダーソン

12

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についてさらに学ぶには:


こんにちはthx。現時点では2つのファイルがありますが、24個のプロセッサーがあるため、一度に多くのペアを実行しようとする気がしました-コンピューティングサイエンスの専門家ではないので、ディスク読み取りのボトルネックが価値があるかどうかはわかりません。たぶん私はそれを吸って見ます;)
スティーブンヘンダーソン14年

@StephenHendersonは、ファイルのサイズに応じて、キャッシュ内にある可能性があります。速度が重要な場合は、tmpfsを使用できます(ファイルは<<<次にRAMです)。
マチェイピエチョトカ14年

1
@StephenHenderson並列ジョブの数は-jで調整できるので、-j4を試してください。サーバーが過負荷にならない場合は、-j6などを試してください。しかし、CTRL-Cを押す準備をしてください:GNU Parallelはサーバーをすぐに過負荷にする優れたツールです。--loadもご覧ください。
オレタンゲ14

1

これを行う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に渡されるstdinに結合する前に、実行を完了するまで待機します。これを使用できる場合waitwhile psループよりも優れていますが、シェルに依存しwaitているため、現在のシェルの子ではないプロセスを待機するように指示すると、反対する可能性があります

また、上記のメソッドは出力を照合するため、両方のプロセスが一度に書き出すことに注意してください。代わりにそれらを別々にしたい場合、または別のものに追加したい場合は、次のようにすることができます:

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

これらの概念を前に示しました。おそらく最高のデモはこちらこちらです。


0

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

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

まあそれは重いものです。wait車輪を再発明するようなものではありませんか?
ジョンWHスミス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.