765 Stimmen

Wie kann man in der Bash warten, bis mehrere Unterprozesse beendet sind, und den Exit-Code !=0 zurückgeben, wenn ein Unterprozess mit dem Code !=0 endet?

Wie kann man in einem Bash-Skript warten, bis mehrere von diesem Skript erzeugte Unterprozesse beendet sind, und dann einen Exit-Code zurückgeben !=0 wenn einer der Unterprozesse mit Code endet !=0 ?

Einfaches Skript:

#!/bin/bash
for i in `seq 0 9`; do
  doCalculations $i &
done
wait

Das obige Skript wartet auf alle 10 gespawnten Unterprozesse, aber es gibt immer den Exit-Status 0 (siehe help wait ). Wie kann ich dieses Skript so ändern, dass es den Exit-Status der gespawnten Unterprozesse erkennt und den Exit-Code 1 wenn einer der Unterprozesse mit Code endet !=0 ?

Gibt es dafür eine bessere Lösung als das Sammeln der PIDs der Unterprozesse, das Warten auf sie in der Reihenfolge und die Summe der Exit-Status?

2 Stimmen

Dies könnte erheblich verbessert werden, um auf folgende Punkte einzugehen wait -n die in der modernen Bash verfügbar ist, um nur zurückzukehren, wenn der erste/nächste Befehl abgeschlossen ist.

0 Stimmen

Wenn Sie mit der Bash testen wollen, versuchen Sie dies: github.com/sstephenson/bats

3 Stimmen

Die aktive Entwicklung von BATS hat sich auf github.com/bats-core/bats-core

744voto

Luca Tettamanti Punkte 9526

wait nimmt auch (optional) die PID des Prozesses zu warten, und mit $! erhalten Sie die PID des zuletzt im Hintergrund gestarteten Befehls. Ändern Sie die Schleife, um die PID jedes gespawnten Unterprozesses in ein Array, und dann eine weitere Schleife, die auf jeden PID .

# run processes and store pids in array
for i in $n_procs; do
    ./procs[${i}] &
    pids[${i}]=$!
done

# wait for all pids
for pid in ${pids[*]}; do
    wait $pid
done

356voto

HoverHell Punkte 4466

http://jeremy.zawodny.com/blog/archives/010717.html :

#!/bin/bash

FAIL=0

echo "starting"

./sleeper 2 0 &
./sleeper 2 1 &
./sleeper 3 0 &
./sleeper 2 0 &

for job in `jobs -p`
do
echo $job
    wait $job || let "FAIL+=1"
done

echo $FAIL

if [ "$FAIL" == "0" ];
then
echo "YAY!"
else
echo "FAIL! ($FAIL)"
fi

127voto

kenorb Punkte 134883

Hier ein einfaches Beispiel mit wait .

Führen Sie einige Prozesse aus:

$ sleep 10 &
$ sleep 10 &
$ sleep 20 &
$ sleep 20 &

Dann warten Sie auf sie mit wait Befehl:

$ wait < <(jobs -p)

Oder einfach wait (ohne Argumente) für alle.

Damit wird gewartet, bis alle im Hintergrund laufenden Aufträge abgeschlossen sind.

Wenn die -n angegeben wird, wartet er auf die Beendigung des nächsten Auftrags und gibt seinen Exit-Status zurück.

Siehe: help wait y help jobs für die Syntax.

Der Nachteil ist jedoch, dass dies nur den Status der letzten ID zurückgibt, so dass Sie den Status für jeden Unterprozess prüfen und in der Variablen speichern müssen.

Oder erstellen Sie eine Berechnungsfunktion, die bei einem Fehler eine Datei erstellt (leer oder mit Fehlerprotokoll), und prüfen Sie dann, ob diese Datei existiert, z. B.

$ sleep 20 && true || tee fail &
$ sleep 20 && false || tee fail &
$ wait < <(jobs -p)
$ test -f fail && echo Calculation failed.

66voto

patapouf_ai Punkte 15406

Wie wäre es mit einfach:

#!/bin/bash

pids=""

for i in `seq 0 9`; do
   doCalculations $i &
   pids="$pids $!"
done

wait $pids

...code continued here ...

Aktualisierung:

Wie von mehreren Kommentatoren angemerkt, wartet das obige System darauf, dass alle Prozesse abgeschlossen sind, bevor es fortgesetzt wird, aber es beendet sich nicht und schlägt fehl, wenn einer von ihnen fehlschlägt:

#!/bin/bash

pids=""
RESULT=0

for i in `seq 0 9`; do
   doCalculations $i &
   pids="$pids $!"
done

for pid in $pids; do
    wait $pid || let "RESULT=1"
done

if [ "$RESULT" == "1" ];
    then
       exit 1
fi

...code continued here ...

54voto

Ole Tange Punkte 1934

Wenn Sie GNU Parallel installiert haben, können Sie das tun:

# If doCalculations is a function
export -f doCalculations
seq 0 9 | parallel doCalculations {}

GNU Parallel gibt Ihnen einen Exit-Code:

  • 0 - Alle Aufträge wurden ohne Fehler ausgeführt.

  • 1-253 - Einige der Aufträge sind fehlgeschlagen. Der Exit-Status gibt die Anzahl der fehlgeschlagenen Aufträge an

  • 254 - Mehr als 253 Aufträge sind fehlgeschlagen.

  • 255 - Sonstiger Fehler.

Sehen Sie sich die Einführungsvideos an, um mehr zu erfahren: http://pi.dk/1

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X