Eseguire il comando o la funzione quando SIGINT o SIGTERM vengono inviati allo script padre stesso, non ai processi figlio


11

Diciamo che ho questo 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

Voglio script.sheseguire la funzione exit_scriptogni volta che riceve SIGINTo SIGTERM Ad esempio:

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

e voglio che il mio script esegua questo

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

Ho provato a implementare questa funzione usando trap

trap exit_script SIGINT SIGTERM

La persona che ha risposto alla mia domanda mi ha dimostrato che mi sbagliavo.
ma non ha funzionato perché trapsembra reagire solo ai segnali inviati a processi secondari / secondari. Come principiante non sono riuscito a decifrare trapla pagina man di così ho probabilmente perso la soluzione.

Immagino sia quello che fanno i programmi "reali" come Chromium quando li invii SIGTERM

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

L'applicazione può determinare cosa vuole fare una volta ricevuto un SIGTERM. Mentre la maggior parte delle applicazioni pulirà le loro risorse e si fermerà, alcune potrebbero non farlo.


2
generalmente le imprecazioni sono considerate inapproriate per un discorso rispettoso
cat

modifica suggerimento approvato ok, ok fatto, niente di divertente lo capisco
bosa djo

non è che non sia permesso divertirsi, è solo considerato offensivo
cat

1
@cat Ho pensato al tuo argomento e hai ragione, scusami per la mia scema
bosa djo

Risposte:


15

trapreagisce ai segnali del processo di chiamata stesso. Ma devi chiamarlo prima di ricevere il segnale. Voglio dire, all'inizio della tua sceneggiatura.

Inoltre, se vuoi usare kill -- -$$, che invia il segnale anche al tuo script, devi cancellare la trappola prima di eseguire l'uccisione o finirai con un ciclo infinito di uccisioni & trap .

Per esempio:

#!/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

Come spiegato nei commenti, il problema è che lo script riceve il segnale ma attende che il programma di sospensione termini prima di elaborare il segnale ricevuto. Quindi, dovresti uccidere i processi figlio (il processo di sospensione in questo caso) per eseguire l'azione trap. Puoi farlo con qualcosa di simile al seguente:

kill -- -$(pgrep script.sh)

O come indicato nei commenti:

killall -g script.sh

1
Probabilmente mi manca qualcosa perché non funziona, ecco cosa faccio. script.sh &; killall script.sh ma non fa nulla.
Bosa Djo,

Eseguo script.sh &; # poi faccio i miei affari; killall script.sh e non uccide script.sh
bosa

1
Il problema probabilmente è che lo script riceve il segnale ma attende che il programma sleep finisca prima di elaborarlo. Prova ./script.sh & sleep 1 && kill -- -$(pgrep script.sh)a inviare un segnale di interruzione anche ai processi figlio della tua sceneggiatura.
zuazo,

@zuazo Dovresti aggiungere queste informazioni interessanti e importanti alla tua risposta :)
cat

1
Bello, bosa djo. Ho aggiunto la tua soluzione alternativa alla risposta ;-)
zuazo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.