[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 reccon el timeoutcomando 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

bgdefgcomandos. De todos modos, ¿hay alguna diferencia entre tus ejemplos primero y 3d?timeouten mi sistema, pero matarsleepfunciona 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ónheady el proceso en ejecuciónsortestá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
timeoutprograma se coloca en su propio grupo de procesos. Del código fuente:Cuando se produce un tiempo de espera,
timeoutpasa 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
timeoutdirectamente en la línea de comando y presiona Ctrl+ C, eltimeoutproceso secundario recibe el SIGINT resultante , pero no el shell interactivo, que estimeoutel proceso principal. Cuandotimeoutse llama desde un script, solo el shell que ejecuta el script recibe la señal:timeoutno 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
trapincorporado. 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
killpara retransmitir la señal altimeoutgrupo 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
timeoutGNU coreutils.Básicamente Ctrl+ Cenvía una
SIGINTseñal, mientras que Ctrl+ Z envía unaSIGTSTPseñal.SIGTSTPsimplemente detiene el proceso, aSIGCONTlo 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.
killlo 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
INTcontrolador:timeoutcomandos con lamy_timeoutfunción en su secuencia de comandos.Ejemplo
Aquí hay un script de ejemplo:
fuente