Experimentar:
#!/bin/bash
_term() {
echo "Caught SIGTERM signal!"
kill -TERM "$child" 2>/dev/null
}
trap _term SIGTERM
echo "Doing some initial work...";
/bin/start/main/server --nodaemon &
child=$!
wait "$child"
Normalmente, bash
ignorará quaisquer sinais enquanto um processo filho estiver em execução. Iniciar o servidor com &
colocará em segundo plano no sistema de controle de tarefas do shell, $!
mantendo o PID do servidor (a ser usado com wait
e kill
). A chamada wait
aguardará a conclusão do trabalho com o PID especificado (o servidor) ou a ativação de qualquer sinal .
Quando o shell recebe SIGTERM
(ou o servidor sai independentemente), a wait
chamada retornará (saindo com o código de saída do servidor ou com o número do sinal + 128 no caso de um sinal ser recebido). Posteriormente, se o shell receber o SIGTERM, ele chamará a _term
função especificada como o manipulador de trap SIGTERM antes de sair (na qual fazemos qualquer limpeza e propagamos manualmente o sinal para o processo do servidor usando kill
).
wait
chamada subseqüente é necessária?exec /bin/start/main/server --nodaemon
(nesse caso, o processo do shell é substituído pelo processo do servidor e você não precisa propagar nenhum sinal) ou usa/bin/start/main/server --nodaemon &
, masexec
não é realmente significativo._term()
função você devewait "$child"
novamente. Isso pode ser necessário se você tiver algum outro processo de supervisão aguardando a morte do script do shell antes de reiniciá-lo novamente ou se você também tiver interceptadoEXIT
a limpeza e precisar executar apenas após a conclusão do processo filho.exec
ou deseja criar armadilhas .O Bash não encaminha sinais como o SIGTERM para processos nos quais está aguardando. Se você deseja finalizar seu script seguindo para o servidor (permitindo manipular sinais e qualquer outra coisa, como se você tivesse iniciado o servidor diretamente), você deve usar o
exec
que substituirá o shell pelo processo que está sendo aberto :Se você precisa manter o shell em torno, por algum motivo (ie. Que você precisa fazer alguma limpeza após o servidor termina), você deve usar uma combinação de
trap
,wait
ekill
. Veja a resposta do SensorSmith .fonte
Andreas Veithen ressalta que, se você não precisar retornar da chamada (como no exemplo do OP), basta chamar o
exec
comando ( a resposta de @Stuart P. Bentley ) é suficiente . Caso contrário, o "tradicional"trap 'kill $CHILDPID' TERM
(resposta de @ cuonglm) é um começo, mas await
chamada realmente retorna depois que o manipulador de trap é executado, o que ainda pode acontecer antes que o processo filho realmente saia. Portanto,wait
é aconselhável uma chamada "extra" ( resposta do @ user1463361 ).Embora isso seja uma melhoria, ele ainda possui uma condição de corrida, o que significa que o processo nunca pode sair (a menos que o sinalizador tente novamente enviar o sinal TERM). A janela de vulnerabilidade está entre o registro do manipulador de armadilhas e o registro do PID da criança.
A seguir, elimina essa vulnerabilidade (empacotada em funções para reutilização).
fonte
A solução fornecida não funciona para mim porque o processo foi interrompido antes que o comando de espera realmente terminasse. Eu descobri que o artigo http://veithen.github.io/2014/11/16/sigterm-propagation.html , o último snippet funciona bem no meu caso de aplicativo iniciado no OpenShift com o sh runner personalizado. O script sh é necessário porque eu preciso ter a capacidade de obter despejos de encadeamento, o que é impossível caso o processo PID do Java seja 1.
fonte