¿Esperar el uso del comando en 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

Esperaba el successestado de salida cuando envío 0, pero todavía recibo failure.

Además, waitno espera 300 segundos. En cambio, recibo el mensaje de inmediato. Supongo que $!es el hijo inmediato de $$mi guión. ¿No es así?

¿Es posible capturar el estado de salida de esperar como exit_status=$(wait $!)?

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

Respuestas:

20

El problema es que estás emitiendo waiten una subshell:

if `wait $!`;then

Debido a que waites un comando incorporado, no un comando, está operando en el subshell , no en su shell actual.

El resultado que vería pero no es es:

wait: pid 12344 is not a child of this shell

... con un estado de retorno de 1.

Para realizar su prueba, deberá hacerlo sin usar una subshell.

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

wait $b && echo success || echo failure

Esto le da el resultado que espera y espera todo el tiempo que espera:

$ 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

Puede verificar el estado de salida de cualquier comando con $?:

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

Hubo un par de otros errores en su script. Tu #!línea estaba malformada, lo que arreglé Usted asigna $!a $b, pero no lo usa $b.

bahamat
fuente
12

Elimina los backticks.

Tal como está, está ejecutando waiten una subshell, que no tiene acceso a los trabajos de la shell principal, por lo que fallará de inmediato.


Si desea el estado de salida, obtenga el valor de $?inmediatamente después de la espera.

command_here &
wait
status=$?
Patricio
fuente
2

Eliminar los backticks hará que el programa funcione, pero no por las razones ya identificadas. Es cierto que waitfalla inmediatamente porque se ejecuta en una subshell y no puede acceder a los procesos de su padre, pero el programa no se ejecutará como se esperaba, incluso si utiliza un comando que funcionó.

La ifinstrucción ejecuta un programa y comprueba si su estado de salida es cero o no cero. Cuando usa backticks, la instrucción if tomará la salida del proceso, intenta ejecutarlo como un programa y luego usa el código de salida para ese proceso. Entonces, el programa no falla porque waitfalla, sino que falla porque waitno produce ningún resultado.

Puede hacer que la secuencia de comandos funcione mediante el uso de echolos backticks:

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

O simplemente elimine los backticks; Más fácil para todos.

Joni
fuente