Estou tentando configurar um script de shell para que ele execute processos em segundo plano e, quando eu Ctrlco script de shell, mata os filhos e sai.
O melhor que eu consegui fazer é esse. Parece que o kill 0 -INT
script também mata o script antes que a espera aconteça; portanto, o script do shell morre antes que os filhos sejam concluídos.
Alguma idéia de como eu posso fazer esse script de shell esperar que as crianças morram após o envio INT
?
#!/bin/bash
trap 'killall' INT
killall() {
echo "**** Shutting down... ****"
kill 0 -INT
wait # Why doesn't this wait??
echo DONE
}
process1 &
process2 &
process3 &
cat # wait forever
Respostas:
Seu
kill
comando está ao contrário.Como muitos comandos UNIX, as opções que começam com menos devem vir primeiro, antes de outros argumentos.
Se você escrever
vê
-INT
como uma opção e enviaSIGINT
para0
(0
é um número especial que significa todos os processos no grupo de processos atual).Mas se você escrever
ele vê o
0
, decide que não há mais opções, então usaSIGTERM
por padrão. E envia isso para o grupo de processos atual, o mesmo que se você fizesse(ele também iria tentar enviar
SIGTERM
para-INT
, o que causaria um erro de sintaxe, mas ele enviaSIGTERM
a0
primeira, e nunca fica tão longe.)Portanto, seu script principal está recebendo um
SIGTERM
antes de executar owait
eecho DONE
.Adicionar
no topo, logo após
e execute-o novamente para provar isso.
Como Stephane Chazelas aponta, seus filhos em segundo plano (
process1
, etc.) ignoramSIGINT
por padrão.De qualquer forma, acho que enviar
SIGTERM
faria mais sentido.Finalmente, não tenho certeza se
kill -process group
é garantido ir primeiro às crianças. Ignorar sinais durante o desligamento pode ser uma boa ideia.Então tente o seguinte:
fonte
Infelizmente, os comandos iniciados em segundo plano são definidos pelo shell para ignorar o SIGINT e, pior ainda, não podem ser ignorados
trap
. Caso contrário, tudo o que você precisa fazer éComo process1 e process2 obteriam o SIGINT quando você pressionar Ctrl-C, pois eles fazem parte do mesmo grupo de processos, que é o grupo de processos em primeiro plano do terminal.
O código acima funcionará com pdksh e zsh que, a esse respeito, não são compatíveis com POSIX.
Com outros shells, você precisaria usar outra coisa para restaurar o manipulador padrão do SIGINT, como:
ou use um sinal diferente como SIGTERM.
fonte
Para aqueles que querem apenas matar um processo e esperar que ele morra, mas não indefinidamente :
Aguarda no máximo 60 segundos por tipo de sinal.
Aviso: Esta resposta não tem nenhuma relação com capturar e enviar um sinal de interrupção.
Ele seleciona o aplicativo para matar por nome ou argumentos. Mantenha os colchetes da primeira letra do nome do aplicativo para evitar a correspondência com o grep.
Com algumas alterações, você pode usar diretamente o PID ou um método mais simples, em
pidof process_name
vez daps
instrução.Detalhes do código: grep final é obter o PID sem os espaços finais.
fonte
Se o que você deseja é gerenciar alguns processos em segundo plano, por que não usar os recursos de controle de tarefas do bash?
fonte
Então, eu brinquei com isso também. No Bash, você pode definir funções e fazer coisas sofisticadas com elas. Meus colegas e eu usamos
terminator
, portanto, para execuções em lote, normalmente geramos um monte de janelas de terminador, se queremos visualizar a saída (menos elegante que astmux
guias, mas você pode usar uma interface mais semelhante à GUI haha).Aqui está a configuração que eu criei, bem como um exemplo de coisas que você pode executar:
Executando
Edite @ Maxim, acabei de ver sua sugestão, que a torna muito mais simples! Obrigado!
fonte