Hacer un bucle hasta que finalice el proceso en segundo plano (con `jobs`) no funciona en el script

Hacer un bucle hasta que finalice el proceso en segundo plano (con `jobs`) no funciona en el script

Estoy intentando realizar un bucle hasta que se complete un proceso en segundo plano (iniciado anteriormente en el script). Un caso de prueba fácilmente reproducible es:

ping -c 10 localhost &>/dev/null &

En la línea de comando, puedo realizar un bucle while [[ -n $(jobs) ]](mientras $(jobs)no es nulo).

$ ping -c 10 localhost &>/dev/null &
[1] 19078
$ while [[ -n $(jobs) ]]; do echo -n .; sleep 1; done
.........[1]+  Done                    ping -c 5 localhost &> /dev/null

Sin embargo, las mismas dos líneas en un script seguirán imprimiendo .s hasta que presione Ctrl-C.

Curiosamente, si llamo jobsdentro del bucle, el script finaliza como se esperaba.

$ ./background-ping.sh
.[1]+  Running                 ping -c 5 localhost &> /dev/null &
.[1]+  Running                 ping -c 5 localhost &> /dev/null &
.[1]+  Running                 ping -c 5 localhost &> /dev/null &
.[1]+  Running                 ping -c 5 localhost &> /dev/null &
.[1]+  Done                    ping -c 5 localhost &> /dev/null

Soy consciente de que existen otras formas de verificar si el trabajo en segundo plano está completo (por ejemplo, verificar /proc), pero quiero saber por qué la verificación jobsno funciona como se esperaba.

Respuesta1

Si entiendo su problema, sus 2 líneas no se detendrán en un script.

Eso es lo que hice en el mío:

ping -c 5 google.com &>/dev/null &
while [[ -n $(jobs -r) ]]; do echo -n "."; sleep 1; done

jobs -rcomprueba los procesos en ejecución y la llamada a mi script funciona como se esperaba, el script se detiene cuando finaliza el ping.

EDITAR: Creo que en un script el proceso principal se conoce como proceso en ejecución y por eso jobssigo pensando que hay un proceso en ejecución. Esa es una hipótesis

¿Es esa la respuesta? (o tal vez realmente no entiendo lo que quieres decir, mi pobre inglés puede ser el problema...)

Respuesta2

Siempre que tenga problemas como este, siempre debe intentar imprimir sus variables para comprender lo que está sucediendo. En este caso, jobstambién devuelve trabajos terminados. Si ejecutas esto:

ping -c 5 localhost &>/dev/null &
while [[ -n $(jobs | tee -a temp) ]]; do
    echo -n .; 
    sleep 1; 
done

Verá el siguiente resultado en temp:

[1]+  Running                 ping -c 5 localhost &> /dev/null &
[1]+  Running                 ping -c 5 localhost &> /dev/null &
[1]+  Running                 ping -c 5 localhost &> /dev/null &
[1]+  Running                 ping -c 5 localhost &> /dev/null &
[1]+  Done                    ping -c 5 localhost &> /dev/null
[1]+  Done                    ping -c 5 localhost &> /dev/null
[1]+  Done                    ping -c 5 localhost &> /dev/null
[1]+  Done                    ping -c 5 localhost &> /dev/null
[1]+  Done                    ping -c 5 localhost &> /dev/null
[...]

Entonces, la salida de jobsaquí nunca está vacía. Incluso cuando el trabajo finaliza, jobstodavía devuelve el Donemensaje. Es por eso que la solución de Metal3d jobs -rfuncionó.

Lo que es más confuso es por qué ejecutar jobsdentro del bucle hace que funcione correctamente. La respuesta tendrá algo que ver con el hecho de que while [[ -n $(jobs) ]]se ejecuta jobsen una subcapa separada, pero no estoy seguro de los detalles. Tengopublicó una preguntasobre esto en U&L si alguien está interesado.

Respuesta3

Puede utilizar waitun comando que espera a que se detengan los trabajos en segundo plano.

Ejemplo:

$ ping -c 10 localhost &>/dev/null &
[29787]
$ wait
[1]+  Done ping -c 10 localhost &>/dev/null

El comando de espera se bloquea y cuando pingfinaliza, se libera el mensaje y luego se imprime un mensaje.

Puedes usarlo con varios comandos:

$ ping -c 5 localhost &>/dev/null & ping -c 5 facebook.com  &>/dev/null &
[1] 29867
[2] 29868
$ wait
[1]-  Done                    ping -c 5 localhost &>/dev/null
[2]+  Done                    ping -c 5 facebook.com &>/dev/null

información relacionada