Ausführen paralleler Prozesse und Kombinieren von Ausgaben, wenn beide abgeschlossen sind

17

Ich habe ein Bash-Shell-Skript, in dem ich einige Daten durch ungefähr 5 oder 6 verschiedene Programme leite und dann das Endergebnis in eine tabulatorgetrennte Datei umwandle.

Ich mache dann dasselbe noch einmal für einen separaten ähnlichen Datensatz und gebe ihn in eine zweite Datei aus.

Anschließend werden beide Dateien zur vergleichenden Analyse in ein anderes Programm eingegeben. zB um zu vereinfachen

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

Meine Frage ist: Wie kann ich step1 und step2 gleichzeitig ausführen lassen (z. B. mit &), aber nur step3 (AnalysisProg) starten, wenn beide abgeschlossen sind?

Danke

ps AnalysisProg funktioniert nicht mit Streams oder Fifos.

Stephen Henderson
quelle
Überprüfen Sie dies: pebblesinthesand.wordpress.com/2008/05/22/…
Bichoy
BTW, ist es in Ordnung für Sie, Perl-Skripte zu verwenden? Dies kann die Angelegenheit für Sie sehr vereinfachen und Sie können diese Nachbearbeitung sehr effizient implementieren und mühelos parallel ausführen.
Bichoy
Perl ... nicht so sehr, nein :(
Stephen Henderson
1
Hier zeige ich, wie man Eingaben über Pipes aufteilttee und mit zwei gleichzeitigen grepProzessen verarbeitet: unix.stackexchange.com/questions/120333/…
mikeserv
Und hier ich zeige , wie einfache Shell - Konstrukte in der Art und Weise zu voll einen Prozess Hintergrund verwenden nohupkönnte , aber immer noch ein Mittel der Kommunikation mit dem Prozess Aufrechterhaltung: unix.stackexchange.com/questions/121253/...
mikeserv

Antworten:

27

Verwenden Sie wait. Beispielsweise:

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

werden:

  • Führen Sie die Pipes Data1 und Data2 als Hintergrundjobs aus
  • Warten Sie, bis beide fertig sind
  • Führen Sie AnalysisProg aus.

Siehe zB diese Frage .

cxw
quelle
Thx, das sieht gut aus. Ich werde es versuchen, wenn das oben nicht funktioniert.
Stephen Henderson
Thx wieder, ich war Art von Wartezeit bewusst, aber ein bisschen gegoogelt war verwirrt, wie es mit verschiedenen PID usw. funktioniert. Ich fühle mich dumm, jetzt sehe ich, es ist nur "warten"
Stephen Henderson
12

Die Antwort von cxw ist zweifellos die bevorzugte Lösung, wenn Sie nur 2 Dateien haben. Wenn die 2 Dateien nur Beispiele sind und Sie in Wirklichkeit 10000 Dateien haben, funktioniert die '&' Lösung nicht, da dies Ihren Server überlasten wird. Dafür benötigen Sie ein Tool wie GNU Parallel:

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

Um mehr über GNU Parallel zu erfahren:

Ole Tange
quelle
Hi thx. Derzeit habe ich zwar zwei Dateien, aber 24 Prozessoren, daher war ich versucht, viele Paare gleichzeitig auszuführen - obwohl ich als Informatiker nicht sicher bin, ob sich der Engpass beim Lesen von Datenträgern lohnen würde. Vielleicht werde ich es saugen und sehen;)
Stephen Henderson
@StephenHenderson Je nach Größe können sich die Dateien noch im Cache befinden. Wenn die Geschwindigkeit kritisch ist, können Sie einfach tmpfs verwenden (und die Dateien sind <<< dann Ihr RAM).
Maciej Piechotka
1
@StephenHenderson Die Anzahl der parallelen Jobs kann mit -j angepasst werden, versuchen Sie es mit -j4, und wenn der Server nicht überlastet wird, versuchen Sie es mit -j6 usw. Halten Sie sich jedoch bereit, STRG-C zu drücken: GNU Parallel ist ein hervorragendes Tool, um Server schnell zu überlasten . Schauen Sie sich auch --load an.
Ole Tange
1

Eine Möglichkeit, dies zu tun, könnte etwa so aussehen:

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

Auf diese Weise hinterlegen Sie beide Pipelines im Hintergrund, warten aber noch, bis die Ausführung abgeschlossen ist, bevor Sie ihre Ausgabe zu stdin kombinieren, das in einem Dokument hier ausgewertet und an AnalysisProg übergeben wird. Wenn Sie dies verwenden können, ist waitdies sogar noch besser als die while psSchleife, kann jedoch, abhängig von der Shell, Einwände erheben, waitwenn Sie sie anweisen, auf einen Prozess zu warten, der kein untergeordnetes Element der aktuellen Shell ist.

Beachten Sie auch, dass bei der oben beschriebenen Methode die Ausgabe sortiert wird, sodass beide Prozesse gleichzeitig ausgeführt werden. Wenn Sie sie stattdessen getrennt oder aneinander angehängt haben möchten, können Sie Folgendes tun:

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

Ich habe diese Konzepte schon einmal demonstriert. Die wahrscheinlich besten Demos gibt es hier und hier .

mikeserv
quelle
0

Versuchen Sie dies.

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
Renan Vicente
quelle
Nun, das ist schwer. Ist es nicht so, als würde man das waitRad neu erfinden ?
John WH Smith