Executar comando ou função quando o SIGINT ou o SIGTERM é enviado para o próprio script pai, não para o filho

11

Digamos que eu tenho isso script.sh

#!/bin/bash
exit_script() {
    echo "Printing something special!"
    echo "Maybe executing other commands!"
    kill -- -$$ # Sends SIGTERM to child/sub processes
}

echo "Some other text"
#other commands here
sleep infinity

Quero script.shexecutar a função exit_scriptsempre que receber SIGINTou SIGTERM Por exemplo:

killall script.sh # it will send SIGTERM to my script

e eu quero que meu script execute isso

exit_script() {
    echo "Printing something special!"
    echo "Maybe executing other commands!"
    kill -- -$$ # Sends SIGTERM to child/sub processes
}

Eu tentei implementar esse recurso usando trap

trap exit_script SIGINT SIGTERM

A pessoa que respondeu à minha pergunta me mostrou errada.
mas não funcionou porque trapparece reagir apenas a sinais enviados a processos secundários / filhos. Como iniciante, não consegui decifrar trapa página de manual do usuário, então provavelmente perdi a solução.

Acho que é isso que programas "reais" como o Chromium fazem quando você os envia SIGTERM

From https://major.io/2010/03/18/sigterm-vs-sigkill/

O aplicativo pode determinar o que deseja fazer quando um SIGTERM for recebido. Embora a maioria dos aplicativos limpe seus recursos e pare, outros podem não.

bosa djo
fonte
2
inapproriate geralmente jura são considerados para o discurso respeitoso
gato
editar sugestão aprovada ok, ok feito, nenhum divertimento eu entendi
bosa djo
não é que nenhum divertimento é permitido, é só que de considerado ofensivo
gato
1
@cat eu pensei sobre o seu argumento e você está certo, desculpe a minha tolice
bosa djo

Respostas:

15

trapreage ao próprio processo de chamada. Mas você deve chamá-lo antes que o sinal seja recebido. Quero dizer, no começo do seu roteiro.

Além disso, se você deseja usar kill -- -$$, o que envia o sinal também para o seu script, você precisa limpar a armadilha antes de executar o kill ou você terminará com um loop infinito de kill && trap .

Por exemplo:

#!/bin/bash
exit_script() {
    echo "Printing something special!"
    echo "Maybe executing other commands!"
    trap - SIGINT SIGTERM # clear the trap
    kill -- -$$ # Sends SIGTERM to child/sub processes
}

trap exit_script SIGINT SIGTERM

echo "Some other text"
#other commands here
sleep infinity

Conforme explicado nos comentários, o problema é que o script recebe o sinal, mas aguarda o término do programa de suspensão antes de processar o sinal recebido. Portanto, você deve matar os processos filhos (neste caso, o processo de suspensão) para executar a ação de interceptação. Você pode fazer isso com algo como o seguinte:

kill -- -$(pgrep script.sh)

Ou como indicado nos comentários:

killall -g script.sh
zuazo
fonte
1
Provavelmente estou perdendo alguma coisa porque não funciona, eis o que faço. script.sh &; killall script.sh, mas não faz nada.
bosa djo
Eu executo o script.sh &; # então eu faço o meu negócio; killall script.sh e não matar script.sh
bosa djo
1
O problema provavelmente é que o script recebe o sinal, mas aguarda o término do programa de suspensão antes de processá-lo. Tente ./script.sh & sleep 1 && kill -- -$(pgrep script.sh)enviar um sinal de interrupção também para os processos filhos do seu script.
Zuazo
@zuazo Você deve adicionar essas informações interessantes e importantes à sua resposta :) #
cat
1
Legal, bosa djo. Eu adicionei a sua solução alternativa para a resposta ;-)
Zuazo