So führen Sie Prozesse parallel aus und kombinieren die Ergebnisse, wenn beide abgeschlossen sind

So führen Sie Prozesse parallel aus und kombinieren die Ergebnisse, wenn beide abgeschlossen sind

Ich habe ein Bash-Shell-Skript, in dem ich einige Daten durch etwa fünf oder sechs verschiedene Programme leite und dann die Endergebnisse in eine durch Tabulatoren getrennte Datei speichere.

Das Gleiche mache ich dann noch einmal für einen separaten, ähnlichen Datensatz und gebe es in eine zweite Datei aus.

Anschließend werden beide Dateien in ein anderes Programm zur vergleichenden Analyse eingegeben. Beispielsweise zur Vereinfachung

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 lautet: Wie kann ich Schritt 1 und Schritt 2 gleichzeitig ausführen (z. B. mit &), aber Schritt 3 (AnalysisProg) erst starten, wenn beide abgeschlossen sind?

Danke

PS: AnalysisProg funktioniert nicht auf einem Stream oder FIFO.

Antwort1

Verwenden Sie wait. Beispiel:

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

Wille:

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

Siehe beispielsweisediese Frage.

Antwort2

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 10.000 Dateien haben, funktioniert die „&“-Lösung nicht, da dies Ihren Server überlasten würde. 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:

Antwort3

Eine Möglichkeit hierfür 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 stellen Sie beide Pipelines in den Hintergrund, warten aber trotzdem, bis sie fertig ausgeführt sind, bevor Sie ihre Ausgabe in stdin kombinieren, das in einem Here-Dokument ausgewertet und an AnalysisProg übergeben wird. Wenn Sie verwenden könnenwaitdas ist sogar noch besser als daswhile psSchleife, aber, abhängig von der Shell,waitkann Einwände erheben, wenn Sie es anweisen, auf einen Prozess zu warten, derist kein untergeordnetes Element der aktuellen Shell.

Beachten Sie auch, dass die obige Methode die Ausgabe sortiert, sodass beide Prozesse gleichzeitig ausgeben. 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 bereits demonstriert. Die wahrscheinlich besten Demos sindHierUndHier.

Antwort4

Versuchen Sie, dies zu verwenden.

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

verwandte Informationen