Angenommen, ich möchte ein paar (sagen wir drei) Programme gleichzeitig ausführen, wie folgt
program1 & program2 & program3 &
Wenn ich ihre wissen will pid's
, denke ich, dass der beste Weg ist, sie zu speichern, so
program1 &
pid1=$!
program2 &
pid2=$!
...
Was aber, wenn ich nun wissen möchte, ob sie beendet sind und wenn ja, welchen Wert sie zurückgegeben haben? Etwa so:
if [ program1 has ended ]; then
do something with its return value
fi
Jede Hilfe wird geschätzt
Antwort1
# launch child process in background
launch_child_process &
# grab child's pid and store it (use array if several)
pid=$!
# later, wait for termination
wait $pid
# show return code from wait, which is actually the return code of the child
echo "Child return code:" $?
Bei mehreren untergeordneten Elementen können Sie natürlich eine Schleife ausführen, um auf jedes PID zu warten und den entsprechenden Rückgabecode abzurufen. Sie verlassen diese Schleife, wenn das letzte untergeordnete Element beendet ist.
Antwort2
Eine einfache Lösung besteht darin, eine Nachricht in eine Protokolldatei zu schreiben
Sagen wir, für Programm 1 machen Sie etwas wie:
#!/bin/bash
.
.
your stuff
.
.
end_time==$(date)
echo "program1 ended at $end_time" > program1_log
Eine andere Lösung wäre, eine leere Datei zu erstellen, um das Prozessende zu markieren.
#!/bin/bash
.
.
your stuff
.
.
echo $? > /some/path/program1_ended #storing the exit value
#disadvantage is that you can't verify if intermediate commands failed.
Dann überprüfen Sie
if [ -e /some/path/program1_ended ]
then
exit_status=$( </some/path/program1_ended )
rm /some/path/program1_ended #Deleting the file, getting ready for next run
.
.
Do something
else
echo "program1 has not ended yet"
fi
Antwort3
POSIX sh ist nicht sehr gut im Umgang mit mehreren Hintergrundprozessen. Das grundlegende Tool ist das wait
eingebaute, das blockiert, bis ein Hintergrundprozess beendet wird. Aber wait
ohne Argument wartet es, bisalleHintergrundprozesse wurden beendet und gibt den Beendigungsstatus des letzten Prozesses zurück, der beendet wurde; der Beendigungsstatus der anderen Unterprozesse geht verloren.
Sie können eine Falle für SIGCHLD setzen, das Signal, das ausgelöst wird, wenn ein untergeordneter Prozess beendet wird. Dadurch wird Code ausgeführt, wenn ein Unterprozess beendet wird. Sie erfahren jedoch nicht unbedingt, welcher Unterprozess beendet wurde oder welchen Rückgabestatus er hat. Verschiedene Shells verhalten sich unterschiedlich.
ATT ksh93 (nicht mksh oder pdksh!) ist die einzige unter den gängigen Shells, die sich bei SIGCHLD-Traps sinnvoll verhält. Sie setzt $!
auf die PID des beendeten Prozesses und $?
auf dessen Rückgabestatus.
#!/bin/ksh
trap 'Process $! (${subprocesses[$!]}) exited with status $?' CHLD
typeset -A subprocesses
program1 & subprocesses[$!]='program1'
program2 & subprocesses[$!]='program2'
wait
Wenn Sie eine andere Shell verwenden, führen Sie alle Nachbehandlungen im Unterprozess durch.
#!/bin/sh
{ program1; echo "program1 exited with status $?"; } &
{ program2; echo "program2 exited with status $?"; } &
wait
Oder verwenden Sie eine leistungsfähigere Sprache wie Perl, Python, Ruby usw.
Antwort4
Wenn Sie ungefähr wissen, in welcher Reihenfolge die Prozesse enden, können Sie wait <pid>
auf die Beendigung warten. Der wait
Befehl übernimmt dann den Beendigungsstatus des Prozesses, auf den gewartet wurde. Beispiel:
if wait $pid1
then echo "$pid1 was ok"
else echo "$pid1 failed with code $?"
fi
Wenn Sie die Reihenfolge nicht kennen, können Sie mit auf einen beliebigen von ihnen warten wait -n $pid1 $pid2 ...
und den Exit-Code auf ähnliche Weise erhalten. Sie erfahren dann jedoch nicht, welcher Prozess beendet wurde. Dies ist jedoch nützlich, wenn Sie nur wissen müssen, ob einer fehlgeschlagen ist.