Warten Sie, bis der Befehl unter Linux ausgeführt wird.

16
#!/bin/bash
function back()
{
    sleep $1
    exit $2
}
back $1 $2 &
b=$!
if `wait $!`;then
    echo success
else
    echo failure
fi
bash-3.00# ./back 300 0
failure
bash-3.00# ./back 300 1
failure

Ich habe successals Exit-Status erwartet, als ich 0 gesendet habe, aber ich erhalte immer noch failure.

Wartet waitauch nicht 300 Sekunden. Stattdessen erhalte ich sofort die Nachricht. Ich gehe davon $!aus, dass es sich $$in meinem Drehbuch um das unmittelbare Kind von handelt . Ist es nicht

Ist es möglich, den Ausgangsstatus des Wartens wie zu erfassen exit_status=$(wait $!)?

if ! ((exit_status));then
    echo sucess
else
    failure
fi
münchen
quelle

Antworten:

20

Das Problem ist, dass Sie waitin einer Subshell ausgeben:

if `wait $!`;then

Da waites sich um einen integrierten Befehl und nicht um einen Befehl handelt, wird er auf der Subshell ausgeführt , nicht auf Ihrer aktuellen Shell.

Die Ausgabe, die Sie sehen würden, aber nicht sehen würden, ist:

wait: pid 12344 is not a child of this shell

... mit einem Rückgabestatus von 1.

Um Ihren Test durchzuführen, müssen Sie auf eine Unterschale verzichten.

#!/bin/bash
function back()
{
  sleep $1
  exit $2
}
back $1 $2 &
b=$!

wait $b && echo success || echo failure

Dies liefert das erwartete Ergebnis und wartet so lange, wie Sie es erwarten:

$ time ./test.sh 3 0
success
./test.sh 3 0  0.00s user 0.01s system 0% cpu 3.012 total
$ time ./test.sh 3 1
failure
./test.sh 3 1  0.00s user 0.01s system 0% cpu 3.012 total

Sie können den Beendigungsstatus jedes Befehls folgendermaßen überprüfen $?:

$ /bin/true
$ echo $?
0
$ /bin/false
$ echo $?
1

Es gab einige andere Fehler in Ihrem Skript. Ihre #!Leitung war fehlerhaft, was ich behoben habe. Sie weisen $!zu $b, aber nicht verwenden $b.

Bahamat
quelle
12

Entfernen Sie die Backticks.

Wie es ist, werden Sie waitin einer Subshell ausgeführt, die keinen Zugriff auf die Jobs der übergeordneten Shell hat und daher sofort fehlschlägt.


Wenn Sie den Exit-Status möchten, erhalten Sie den Wert von $?unmittelbar nach dem Warten.

command_here &
wait
status=$?
Patrick
quelle
2

Durch das Entfernen der Backticks funktioniert das Programm, jedoch nicht vollständig aus den bereits identifizierten Gründen. Es stimmt , dass waitsofort fehlschlägt , weil es in einer Subshell ausgeführt wird und kann nicht seine Eltern Prozesse zugreifen, aber das Programm nicht wie erwartet ausgeführt , auch wenn Sie einen Befehl verwendet , die Arbeit getan hat.

Die ifAnweisung führt ein Programm aus und prüft, ob sein Exit-Status Null oder Nicht-Null ist. Wenn Sie Backticks verwenden, verwendet die if-Anweisung die Ausgabe des Prozesses, versucht, ihn als Programm auszuführen, und verwendet dann den Exit-Code für diesen Prozess. Das Programm waitschlägt waitalso nicht fehl, weil es fehlschlägt, sondern weil es keine Ausgabe erzeugt.

Sie können das Skript echozum Laufen bringen, indem Sie die folgenden Backticks verwenden:

if `echo wait $!`; then
    echo success
else
    echo failure
fi

Oder entfernen Sie einfach die Backticks. einfacher für alle.

Joni
quelle