Warten Sie mehrere Prozesse ab und drucken Sie den Exit-Code, wenn ein Prozess beendet wird.

Warten Sie mehrere Prozesse ab und drucken Sie den Exit-Code, wenn ein Prozess beendet wird.

Was ich hier erreichen möchte, ist, dass ich über ein Skript drei verschiedene benutzerdefinierte Anwendungen gleichzeitig im Wartemodus laufen lasse. Wenn eine der Anwendungen beendet wird, gebe ich per Benachrichtigung eine Warnung aus oder drucke den Exit-Code aus.

Verwendetes System: Centos 6.8

Antwort1

Der waitBefehl in bash(4.3 und neuer) hat eine -nOption:

Wenn die -nOption angegeben ist, wartet „wait“ auf die Beendigung eines Jobs und gibt seinen Beendigungsstatus zurück.

Das bedeutet, dass Sie

command1 &
command2 &
command3 &

wait -n
printf 'One command exited with exit code %d\n' "$?"

Antwort2

Sie können mit wait -nwarten, bis ein untergeordnetes Element beendet wird, und dann für jedes untergeordnete Element testen, ob es noch mit ausgeführt wird kill -0, um zu sehen, welches gerade beendet wurde. Gehen Sie dazu folgendermaßen vor:

for f in 15 10 15; do
    sleep $f &
    PIDS+="$! "
done
wait -n
for f in $PIDS; do
    if ! kill -0 $f 2> /dev/null; then
        echo $f
    fi
done

wait -nGibt nur den Beendigungsstatus des untergeordneten Elements zurück, nicht, welcher PIDes war.

Antwort3

Ich habe an Bash gedacht wait -n, aber es teilt einem nicht mit, welcher Kindprozess beendet wurde. Wie wäre es mit einem einfachen Perl-Skript?

#!/usr/bin/perl

use strict;
use warnings;
use POSIX ":sys_wait_h";

sub spawn(@) {
    my $pid = fork();
    die "fork: $!" if not defined $pid;
    if ($pid == 0) {
        exec @_ or die "exec: $!";
    }
    return $pid;
}

# Commands to run
my $p1 = spawn '/bin/bash -c "sleep 6; kill $$"';
my $p2 = spawn '/bin/bash -c "sleep 4; exit 4"';

print "spawned PIDs $p1 and $p2\n";

while ((my $child = waitpid(-1, 0)) > 0) {
    my $code = $? >> 8;
    my $status = $? & 0xff;
    printf "child %d finished with exit code %d (status/sig %d)\n", $child, $code, $status;
}

Antwort4

Mit Bash 5.1 oder neuer können Sie Folgendes tun:

while
  wait -np id
  status=$?
  [ -n "$id" ]
do
  echo "process of ID $id exited with status $status"
done
bash-5.2$ Hilfe warte
Warten:Warten[-FN] [-p var] [Ausweis...]
    Warten Sie, bis der Auftrag abgeschlossen ist, und geben Sie den Beendigungsstatus zurück.

    Wartet auf jeden Prozess, der durch eine ID identifiziert wird. Dies kann eine Prozess-ID oder eine
    Auftragsspezifikation und meldet seinen Beendigungsstatus. Wenn die ID nicht
    gegeben, wartet auf alle derzeit aktiven Kindprozesse und die Rückgabe
    Status ist Null. Wenn die ID eine Auftragsspezifikation ist, wartet auf alle Prozesse
    in der Pipeline dieses Jobs.

    Wenn die Option -n angegeben ist, wird auf einen einzelnen Job aus der Liste der IDs gewartet.
    oder, wenn keine IDs angegeben sind, für den nächsten Auftrag, der abgeschlossen werden soll, und gibt seine
    Beendigungsstatus.

    Wenn die Option -p angegeben ist, die Prozess- oder Jobkennung des Jobs
    für die der Exit-Status zurückgegeben wird, wird der Variablen VAR zugewiesen.
    benannt durch das Optionsargument. Die Variable wird zunächst gelöscht, bevor
    beliebige Zuweisung. Dies ist nur sinnvoll, wenn die Option -n angegeben ist.

    Wenn die Option -f angegeben ist und die Jobsteuerung aktiviert ist, wartet
    angegebene ID zum Beenden, anstatt auf eine Statusänderung zu warten.

    Beendigungsstatus:
    Gibt den Status der letzten ID zurück; schlägt fehl, wenn die ID ungültig ist oder ein ungültiger
    Option angegeben ist, oder wenn -n angegeben ist und die Shell keine unwaited-for-
    Kinder.

verwandte Informationen