Poczekać na użycie komendy w systemie Linux?

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

Oczekiwałem successstatusu wyjścia, gdy wysyłam 0, ale wciąż otrzymuję failure.

Ponadto waitnie czeka przez 300 sekund. Zamiast tego natychmiast otrzymuję wiadomość. Zakładam, że $!jest to bezpośrednie dziecko $$w moim skrypcie. Czyż nie

Czy można uchwycić status wyjścia oczekiwania, jak exit_status=$(wait $!)?

if ! ((exit_status));then
    echo sucess
else
    failure
fi
Munish
źródło

Odpowiedzi:

20

Problem polega na tym, że wydajesz waitw podpowłoce:

if `wait $!`;then

Ponieważ waitjest wbudowany, a nie polecenie, działa na podpowłoce , a nie na bieżącej powłoce.

Dane wyjściowe, które można zobaczyć, ale nie są to:

wait: pid 12344 is not a child of this shell

... ze statusem zwrotu 1.

Aby wykonać test, musisz to zrobić bez użycia podpowłoki.

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

wait $b && echo success || echo failure

Daje to oczekiwany wynik i czeka tak długo, jak się spodziewasz:

$ 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

Możesz sprawdzić status wyjścia dowolnego polecenia za pomocą $?:

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

W twoim skrypcie było kilka innych błędów. Twoja #!linia była zniekształcona, co naprawiłem. Przypisać $!do $b, ale nie używać $b.

bahamat
źródło
12

Usuń wsteczne.

W tej chwili wykonujesz waitw podpowłoce, która nie ma dostępu do zadań powłoki nadrzędnej, więc natychmiast się nie powiedzie.


Jeśli chcesz uzyskać status wyjścia, uzyskaj wartość $?natychmiast po odczekaniu.

command_here &
wait
status=$?
Patrick
źródło
2

Usunięcie backticków sprawi, że program będzie działał, ale nie całkowicie z powodów już zidentyfikowanych. To prawda, że waitnatychmiast kończy się niepowodzeniem, ponieważ działa w podpowłoce i nie może uzyskać dostępu do procesów swojego rodzica, ale program nie działałby zgodnie z oczekiwaniami, nawet gdybyś użył polecenia, które działało.

ifOświadczenie uruchamia program i sprawdza, jeśli jego kod wyjścia jest równy zero lub niezerową. Podczas korzystania z odwrotnych instrukcji if pobiera dane wyjściowe procesu, spróbuj uruchomić je jako program, a następnie użyj kodu zakończenia dla tego procesu. Więc program nie waitzawiedzie, ponieważ zawiedzie, ale raczej zawiedzie, ponieważ waitnie generuje żadnych danych wyjściowych.

Możesz sprawić, by skrypt działał, korzystając echoz backticks:

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

Lub po prostu usuń backticks; łatwiej dla wszystkich.

Joni
źródło