Ho uno script Bash che esegue un processo in esecuzione prolungata in primo piano. Quando riceve un segnale SIGQUIT, dovrebbe eseguire varie operazioni di pulizia come uccidere se stesso e tutti i suoi processi figli (tramite kill del gruppo di processi ecc.). Uno script minima, che dovrebbe prendere il segnale, è mostrato di seguito (chiamato test_trap.sh
):Come utilizzare Trap in modo affidabile utilizzando Bash in esecuzione processi figlio in primo piano
#!/bin/bash
trap 'echo "TRAP CAUGHT"; exit 1' QUIT # other required signals are omitted for brevity
echo starting sleep
sleep 11666
echo ending sleep
echo done
vorrei inviare il segnale SIGHUP al processo dello script test_trap.sh
. Tuttavia, l'invio di un SIGHUP a test_trap.sh
non attiva l'espressione trap ma solo quando invio il segnale al processo figlio sleep 11666
fa il trap. Qui di seguito è una sessione bash che dimostra questo:
bash-4.1$ test_trap.sh &
[1] 19633
bash-4.1$ starting sleep
bash-4.1$ kill -s SIGQUIT 19633
bash-4.1$ jobs
[1]+ Running test_trap.sh &
bash-4.1$ ps -ef --forest --cols=10000 | grep '11666\|test_trap.sh' | grep -v grep
theuser 19633 12227 0 07:40 pts/4 00:00:00 \_ /bin/bash ./test_trap.sh
theuser 19634 19633 0 07:40 pts/4 00:00:00 | \_ sleep 11666
bash-4.1$ kill -s SIGQUIT 19634
bash-4.1$ Quit (core dumped)
TRAP CAUGHT
[1]+ Exit 1 test_trap.sh
bash-4.1$ ps -ef --forest --cols=10000 | grep '11666\|test_trap.sh' | grep -v grep
bash-4.1$
Si noti che il "11666 sleep" è solo un processo rappresentativo. Tale processo può effettivamente essere una subshell interattiva (ad es., bash -i
).
Perché il processo padre test_trap.sh
non rileva il segnale SIGHUP? Perché la trappola si attiva solo quando è stata segnalata la procedura per sleep 11666
?
Non desidero utilizzare SIGKILL non acquisibile poiché è necessario eseguire un assortimento di operazioni di pulitura nell'espressione trap.
Questo script è destinato a essere eseguito su qualsiasi versione abbastanza recente di qualsiasi distribuzione Linux contenente Bash (ad esempio, non Cygwin).
Riferimenti:
Devo contrassegnarlo come la risposta da quando hai fatto la mia domanda ed è stato abbastanza utile. Tuttavia, ho detto "Quel processo può essere in realtà una subshell interattiva (ad es. Bash -i)." E avrei dovuto aggiungere "Non voglio mettere il processo rappresentativo in background perché potrebbe essere una shell interattiva". – bgoodr
Ricordare che l'utente della subshell interattiva potrebbe comunque impostare i propri trap per evitare che la shell venga interrotta dal chiamante. – chepner
@bgoodr hai mai trovato una soluzione che non richieda la messa in background del processo? – trex005