bash – código de retorno confiable del proceso en segundo plano

Pregunta:

Supongamos la siguiente pieza de código bash:

foo > logfile 2>&1 &
foo_pid=$!

while ps -p$foo_pid
do
    ping -c 1 localhost
done

wait $foo_pid

if [[ $? == 0 ]]
then
    echo "foo success"
fi

¿Es seguro asumir que $? de hecho contiene el código de retorno de foo y no el código de retorno de ping ? Si la respuesta a esa pregunta es: "No puedes asumir eso". entonces, ¿cómo puedo modificar este fragmento de código para asegurarme de que $? siempre contiene el código de retorno de foo ?

Respuesta:

Con bash , tendrá esa garantía a menos que haya comenzado otro trabajo en segundo plano (y tenga en cuenta que los trabajos en segundo plano se pueden iniciar con & pero también con coproc y con sustitución de proceso) entre foo & y wait .

POSIX requiere que un shell recuerde el estado de salida de al menos 25 trabajos después de que se hayan ido , pero bash recuerda mucho más que eso.

Ahora, si lo hace:

foo & pid=$!
...
bar &
wait "$pid"

No tienes garantía de que a bar no se le dará el mismo pid que foo (si foo ha terminado antes de que comience la bar ), así que aunque es poco probable, wait "$pid" puede darte el estado de salida de bar .

Puedes reproducirlo con:

bash -c '(exit 12; foo) & pid=$!
         while : bar & [ "$pid" != "$!" ]; do :;done
         wait "$pid"; echo "$?"'

que (eventualmente) le dará 0 lugar de 12 .

Para evitar el problema, una forma sería escribirlo como:

{
  foo_pid=$!

  while ps -p "$foo_pid"
  do
      ping -c 1 localhost
  done

  bar &
  ...

  read <&3 ret
  if [ "$ret" = 0 ]; then
    echo foo was sucessful.
  fi
} 3< <(foo > logfile 2>&1; echo "$?")

Leave a Comment

Your email address will not be published.

Scroll to Top

istanbul avukat

-

web tasarım