Bash - Exit Status von Hintergrundjobs ermitteln

Thomas Michalka <[email protected]> Thu, 28 Jan 2010 18:32:57 +0100
Newsgroups gmane.linux.suse.programming
Message-ID <[email protected]>
Liebe MitListige,


intensive Recherchen in der Manpage und gedruckter Literatur zur Bash
sowie in Mailinglistenarchiven haben zu folgendem Vorhaben nichts
nennenswertes ergeben:

Ich möchte in einem Skript mehrere Hintergrundjobs nacheinander starten,
d.h. die Bash soll (zunächst) nicht warten, bis einer fertig ist,
sondern alle Jobs auf die Reise schicken und danach gleich wieder
weitere Anweisungen synchron ausführen. Weiter unten im Skript soll dann
jedoch auf die Rückkehr (die Beendigung) aller Jobs gewartet werden,
wobei die Rückgabewerte aller Hintergrundjobs ermittelt werden sollen.
So könnte das in etwa aussehen:

# Alle Backups parallel laufen lassen
for SRC_DIR in $SRC_DIR_LIST ; do
    rsync <options> $SRC_DIR $DEST_DIR &
    PID_LIST="$! "
done

# Weitere Anweisungen, synchron zur for-Schleife
...
...
...
# Jetzt aber auf den Abschluss aller Backups warten
wait $PID_LIST
exit_status=$?

# Der Rest des Skripts kommt hier ...
...

... aber auch das Problem:
man weiß nicht, in welcher Reihenfolge die Jobs fertig werden. Bei dem
wait-Kommando dürfte anschließend in exit_status nur derjenige des
zuletzt terminierenden rsync-Prozesses stehen.
Was aber passiert, wenn man in einer weiteren Schleife die Rückgabewerte
aller rsync-Prozesse ermittelt, etwa so:

for PID in $PID_LIST ; do
    wait $PID
    exit_status_list="$? "
done

Hier zweifle ich stark, ob das überhaupt funktioniert, denn

1.
Hier wird der Sinn der oben gewollten Asynchronität der Hintergrundjobs
konterkariert, weil für eine PID, deren Prozess noch nicht terminiert
ist, in dieser for-Schleife gewartet wird, bis er beendet ist.
2.
Es ist nicht klar, ob wait $PID bei einem vor der for-Schleife schon
beendeten Job noch den exit_status zurückgibt und was demnach in der
exit_status_list landet.


Ein simples abschließendes wait ohne Parameter würde die Shell bis zur
Terminierung des letzten Hintergrundjobs warten lassen, aber leider
bekommt man dann als Rückgabewert nur 0, was nichts über den Erfolg oder
Misserfolg der Hintergrundprozesse aussagt.

Willkommen wäre mir ein Hinweis, wo man solche grundlegenden
Bash-Programmier-Fragen und -Lösungen nachschlagen kann.
Vielen Dank schon mal für die Mühe!


Gruß, Tom



P.S.: Folgenden Bash-Manpage-Ausschnitte waren für mich zunächst Grundlage:

"If  a command is terminated by the control operator &, the shell
executes the command in the background in a subshell.  The shell does
not wait for the command to finish, and the return status is 0 [Anm: der
Subshell].  Commands separated by a ; are executed sequentially; the
shell waits for each command to terminate in turn.  The return status
[Anm.: der das Kommando startenden Shell] is the exit status of the last
command executed"

"wait [n ...]
              Wait for each specified process and return its termination
status.  Each n may be a process ID or a job specification; if a job
spec is given, all  processes  in  that  job's pipeline are waited for.
 If n is not given, all currently active child processes are waited for,
and the return status is zero.
              If n specifies a non-existent process or job, the return
status is 127.  Otherwise, the return status is the exit status of  the
 last  process  or  job waited for."
-- 
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]