Las teclas de señal como Ctrl+ Cenvían una señal a todos los procesos en el grupo de procesos en primer plano .
En el caso típico, un grupo de procesos es una tubería. Por ejemplo, en head <somefile | sort
, el proceso en ejecución head
y el proceso en ejecución sort
están en el mismo grupo de procesos, al igual que el shell, por lo que todos reciben la señal. Cuando ejecuta un trabajo en segundo plano ( somecommand &
), ese trabajo está en su propio grupo de procesos, por lo que presionar Ctrl+ Cno lo afecta.
El timeout
programa se coloca en su propio grupo de procesos. Del código fuente:
/* Ensure we're in our own group so all subprocesses can be killed.
Note we don't just put the child in a separate group as
then we would need to worry about foreground and background groups
and propagating signals between them. */
setpgid (0, 0);
Cuando se produce un tiempo de espera, timeout
pasa por el simple recurso de eliminar el grupo de procesos del que es miembro. Como se ha colocado en un grupo de proceso separado, su proceso padre no estará en el grupo. El uso de un grupo de procesos aquí garantiza que si la aplicación secundaria se bifurca en varios procesos, todos sus procesos recibirán la señal.
Cuando se ejecuta timeout
directamente en la línea de comando y presiona Ctrl+ C, el timeout
proceso secundario recibe el SIGINT resultante , pero no el shell interactivo, que es timeout
el proceso principal. Cuando timeout
se llama desde un script, solo el shell que ejecuta el script recibe la señal: timeout
no la recibe ya que está en un grupo de proceso diferente.
Puede establecer un controlador de señal en un script de shell con el trap
incorporado. Lamentablemente, no es tan simple. Considera esto:
#!/bin/sh
trap 'echo Interrupted at $(date)' INT
date
timeout 5 sleep 10
date
Si presiona Ctrl+ Cdespués de 2 segundos, esto todavía esperará los 5 segundos completos, luego imprima el mensaje "Interrumpido". Esto se debe a que el shell se abstiene de ejecutar el código de captura mientras un trabajo en primer plano está activo.
Para remediar esto, ejecute el trabajo en segundo plano. En el controlador de señal, llame kill
para retransmitir la señal al timeout
grupo de procesos.
#!/bin/sh
trap 'kill -INT -$pid' INT
timeout 5 sleep 10 &
pid=$!
wait $pid
bg
defg
comandos. De todos modos, ¿hay alguna diferencia entre tus ejemplos primero y 3d?