Attendere l'utilizzo del comando in 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

Mi aspettavo successcome stato di uscita quando invio 0, ma sto ancora ricevendo failure.

Inoltre, waitnon aspetta 300 secondi. Invece, ricevo immediatamente il messaggio. Presumo $!sia il figlio immediato di $$nella mia sceneggiatura. No?

È possibile acquisire lo stato di uscita di wait like exit_status=$(wait $!)?

if ! ((exit_status));then
    echo sucess
else
    failure
fi

Risposte:


20

Il problema è che stai emettendo waitin una subshell:

if `wait $!`;then

Perché waitè un builtin, non un comando, sta funzionando sulla subshell , non sulla shell corrente.

L'output che vorresti vedere ma non lo è è:

wait: pid 12344 is not a child of this shell

... con uno stato di ritorno di 1.

Per eseguire il test è necessario farlo senza utilizzare una subshell.

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

wait $b && echo success || echo failure

Questo dà il risultato che ti aspetti e aspetta tutto il tempo che ti aspetti:

$ 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

Puoi controllare lo stato di uscita di qualsiasi comando con $?:

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

Ci sono stati un paio di altri errori nella tua sceneggiatura. La tua #!linea era malformata, che ho corretto. Assegni $!a $b, ma non usi $b.


12

Rimuovere i backtick.

Così waitcom'è , stai eseguendo in una subshell, che non ha accesso ai lavori della shell genitrice, quindi fallirà immediatamente.


Se si desidera lo stato di uscita, ottenere il valore di $?immediatamente dopo l'attesa.

command_here &
wait
status=$?

2

La rimozione dei backtick farà funzionare il programma, ma non interamente a causa dei motivi già identificati. È vero che waitfallisce immediatamente perché viene eseguito in una subshell e non può accedere ai processi dei suoi genitori, ma il programma non funzionerebbe come previsto anche se si usasse un comando che funzionava.

L' ifistruzione esegue un programma e verifica se il suo stato di uscita è zero o diverso da zero. Quando si utilizzano i backtick, l'istruzione if prenderà l' output del processo, tenterà di eseguirlo come programma e quindi utilizzerà il codice di uscita per quel processo. Quindi il programma non fallisce perché waitfallisce, ma piuttosto fallisce perché waitnon produce alcun output.

Puoi far funzionare lo script usando echoall'interno dei backtick:

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

O semplicemente rimuovere i backtick; più facile per tutti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.