[Editar: Esto se parece a algunas otras preguntas sobre cómo matar todos los procesos generados; todas las respuestas parecen ser el uso de pkill. Entonces, el núcleo de mi pregunta puede ser: ¿Hay alguna forma de propagar Ctrl-C / Z a todos los procesos generados por un script?]
Al llamar a un SoX rec
con el timeout
comando de coreutils (discutido aquí ), no parece haber ninguna forma de matarlo con una pulsación de tecla una vez que se invoca desde un script Bash.
Ejemplos:
timeout 10 rec test.wav
... se puede matar con Ctrl+ Co Ctrl+ Zdesde bash, pero no cuando se ha llamado desde dentro de un script.
timeout 10 ping nowhere
... se puede matar con Ctrl+ Co Ctrl+ Zdesde bash, y con Ctrl+ Zcuando se ejecuta desde un script.
Puedo encontrar la ID del proceso y matarlo de esa manera, pero ¿por qué no puedo usar una tecla de interrupción estándar? ¿Y hay alguna forma de estructurar mi script para que pueda?
fuente
bg
defg
comandos. De todos modos, ¿hay alguna diferencia entre tus ejemplos primero y 3d?timeout
en mi sistema, pero matarsleep
funciona si se escribe directamente en la línea de comando, se obtiene, se ejecuta o se pasa explícitamente por el intérpreteRespuestas:
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ónhead
y el proceso en ejecuciónsort
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: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, eltimeout
proceso secundario recibe el SIGINT resultante , pero no el shell interactivo, que estimeout
el proceso principal. Cuandotimeout
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: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 altimeout
grupo de procesos.fuente
Sobre la base de la excelente respuesta proporcionada por Gilles. El comando de tiempo de espera tiene una opción de primer plano; si se usa, CTRL + C saldrá del comando de tiempo de espera.
fuente
timeout
GNU coreutils.Básicamente Ctrl+ Cenvía una
SIGINT
señal, mientras que Ctrl+ Z envía unaSIGTSTP
señal.SIGTSTP
simplemente detiene el proceso, aSIGCONT
lo continuará.Esto funciona en el proceso de primer plano que se bifurcó en la línea de comandos.
Si su proceso es un proceso en segundo plano, deberá enviar esa señal a los procesos de una manera diferente.
kill
lo haré. En teoría, un operador "-" en ese kill también debería indicar los procesos secundarios, pero esto rara vez funciona como se esperaba.Para más información: Señales Unix
fuente
Mejorando la respuesta de @Gilles proporcionando un enfoque de "buscar y reemplazar" para los scripts existentes
INT
controlador:timeout
comandos con lamy_timeout
función en su secuencia de comandos.Ejemplo
Aquí hay un script de ejemplo:
fuente