Debe faltarme algo aquí:
#!/bin/bash
timeout 5 sleep 10 &
parent_pid=$( ps --pid $! -o ppid --no-headers )
timeout_pid=$( pgrep --parent $parent_pid timeout )
wait $timeout_pid
echo "exit code: $?"
Llame al script wait-pid
y ejecute:
$ ./wait-pid
exit code: 124
que es lo que esperaba, timeout
finaliza el sleep
proceso y sale con 124, que wait
regresa obedientemente.
Pero si agrego una canalización al comando inicial:
timeout 5 sleep 10 | cat &
parent_pid=$( ps --pid $! -o ppid --no-headers )
timeout_pid=$( pgrep --parent $parent_pid timeout )
wait $timeout_pid
echo "exit code: $?"
ahora me sale:
$ ./wait-pid
exit code: 0
Aún no debería wait
devolver el código de salida del proceso que está esperando: timeout
. Entonces, ¿el código de salida no debería seguir siendo 124?
Esto es con la versión bash 4.4.20(1).
Respuesta1
Recibí una respuesta del experto Greg Woolge en la lista de correo de bash. El elemento clave es:
El comando de espera solo funciona en procesos secundarios directos del shell, también conocidos como "comandos asíncronos". En el caso de que su comando asincrónico sea una canalización, recurriremos al conjunto de características sh original. El estado de salida de su comando asincrónico es el del último comando en la canalización, y los estados de salida de los otros comandos simplemente se descartan.
Es por eso que no obtengo el código de salida de timeout
cuando está en una tubería.
La forma de obtener el comportamiento que deseo es utilizar un archivo temporal para capturar códigos de salida desde el código asincrónico. Algo como:
{
timeout 5 sleep 10 | cat
echo "${PIPESTATUS[@]}" > "$tempfile"
} &
wait