[Editar: Isso é semelhante a algumas outras perguntas perguntando como matar todos os processos gerados - as respostas parecem usar o pkill. Portanto, o núcleo da minha pergunta pode ser: Existe uma maneira de propagar Ctrl-C / Z para todos os processos gerados por um script?]
Ao chamar um SoX rec
com o timeout
comando coreutils (discutido aqui ), não parece haver nenhuma maneira de matá-lo com um pressionamento de tecla depois que ele é chamado a partir de um script Bash.
Exemplos:
timeout 10 rec test.wav
... pode ser morto com Ctrl+ Cou Ctrl+ Zdo bash, mas não quando é chamado de dentro de um script.
timeout 10 ping nowhere
... pode ser morto com Ctrl+ Cou Ctrl+ Zdo bash e com Ctrl+ Zquando executado dentro de um script.
Posso encontrar o ID do processo e matá-lo dessa maneira, mas por que não consigo usar um pressionamento de tecla de quebra padrão? E existe alguma maneira de estruturar meu script para que eu possa?
fonte
bg
defg
comandos. De qualquer forma, existe alguma diferença entre os exemplos 1 e 3?timeout
no meu sistema, mas matandosleep
obras se ele está digitado diretamente na linha de comando, origem, executado ou passaram pelo intérprete explicitamenteRespostas:
Teclas de sinal como Ctrl+ Cenviam um sinal para todos os processos no grupo de processos em primeiro plano .
No caso típico, um grupo de processos é um pipeline. Por exemplo, em
head <somefile | sort
, o processo em execuçãohead
e o processo em execuçãosort
estão no mesmo grupo de processos, assim como o shell, para que todos recebam o sinal. Quando você executa um trabalho em segundo plano (somecommand &
), esse trabalho está em seu próprio grupo de processos; portanto, pressionar Ctrl+ Cnão o afeta.O
timeout
programa se coloca em seu próprio grupo de processos. Do código fonte:Quando ocorre um tempo limite,
timeout
passa pelo simples expediente de matar o grupo de processos do qual ele é membro. Como se colocou em um grupo de processos separado, o processo pai não estará no grupo. O uso de um grupo de processos aqui garante que, se o aplicativo filho for dividido em vários processos, todos os seus processos receberão o sinal.Quando você executa
timeout
diretamente na linha de comando e pressiona Ctrl+ C, o SIGINT resultante é recebido pelotimeout
processo filho e por ele, mas não pelo shell interativo, que étimeout
o processo pai do processo. Quandotimeout
é chamado de um script, somente o shell que executa o script recebe o sinal:timeout
não o recebe, pois está em um grupo de processos diferente.Você pode definir um manipulador de sinal em um script de shell com o
trap
builtin. Infelizmente, não é assim tão simples. Considere isto:Se você pressionar Ctrl+ Capós 2 segundos, isso ainda aguarda os 5 segundos completos e imprima a mensagem “Interrompido”. Isso ocorre porque o shell evita executar o código de interceptação enquanto um trabalho em primeiro plano está ativo.
Para remediar isso, execute o trabalho em segundo plano. No manipulador de sinal, chame
kill
para retransmitir o sinal para otimeout
grupo de processos.fonte
Com base na excelente resposta fornecida por Gilles. O comando timeout tem uma opção em primeiro plano, se usado, um CTRL + C sairá do comando timeout.
fonte
timeout
GNU coreutils.Basicamente Ctrl+ Cenvia um
SIGINT
sinal, enquanto Ctrl+ Z envia umSIGTSTP
sinal.SIGTSTP
apenas interrompe o processo, aSIGCONT
continuará.Isso funciona no processo de primeiro plano que foi bifurcado na linha de comando.
Se o seu processo for um processo em segundo plano, você precisará enviar esse sinal para os processos de uma maneira diferente.
kill
vai fazer isso. Em teoria, um operador "-" nessa matança também deve sinalizar processos filhos, mas isso raramente funciona como o esperado.Para leitura adicional: Unix-Signals
fonte
Melhorando a resposta do @Gilles, fornecendo uma abordagem "localizar e substituir" para scripts existentes:
INT
manipulador:timeout
comandos pelamy_timeout
função em seu script.Exemplo
Aqui está um exemplo de script:
fonte