
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:
- Sehen Sie sich das Einführungsvideo für eine kurze Einführung an: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
- Gehen Sie das Tutorial durch (man parallel_tutorial). Ihre Kommandozeile wird es Ihnen danken.
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önnenwait
das ist sogar noch besser als daswhile ps
Schleife, aber, abhängig von der Shell,wait
kann 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