Come intrappolo correttamente SIGQUIT in uno script bash?
Domanda
Posso scrivere script della shell che intercettano SIGINT
bene, ma non riesco a intercettare SIGQUIT
.
#!/bin/bash
function die {
echo "Dying on signal $1"
exit 0
}
trap 'die "SIGINT"' SIGINT
trap 'die "SIGQUIT"' SIGQUIT
while true; do
echo "sleeping..."
sleep 5
done
L'esecuzione di questo script e la pressione di CTRL-C
ha l'effetto desiderato, ma premendo CTRL-\
(che, a quanto ho capito, dovrebbe attivare SIGQUIT
) non fa altro che stampare ^\
nel terminale. Perché?
Ho due teorie correnti. Il primo è che la semantica di SIGINT
e SIGQUIT
è diversa in modo tale che SIGQUIT
viene inviato solo al processo figlio sleep
, mentre SIGINT
viene inviato sia al processo figlio che al processo bash genitore. Se questo è il caso, dove è documentato?
La mia seconda teoria è che bash non solo ignora (cioè, ha un gestore no-op per) SIGQUIT
per impostazione predefinita (come suggerisce la pagina man), ma non gli consente affatto di essere intrappolato. Questa teoria si sovrappone alla prima teoria, poiché potrebbe essere il caso che SIGQUIT
vada sia al genitore che al figlio, ma il genitore (bash
) non può semplicemente intercettarlo. Se questo è il caso, esiste qualche modo per intercettare SIGQUIT
in uno script bash? ... forse qualche shopt
che posso impostare?
Modifica: questo è su Ubuntu 10.10 in gnome-terminal 2.32.0 con bash 4.1.5, e sì, ^\
è configurato per emettere SIGQUIT (come riportato da stty -a
e confermato dall'emissione di ^\
SIGQUIT ad altri programmi come ping
).
AGGIORNAMENTO:
Ho appena scoperto che il problema deve essere dovuto in qualche modo a gnome-terminal. Se eseguo questo script da una console virtuale (ad esempio, ctrl-alt-f1
per uscire da X), intercetta perfettamente SIGQUIT quando premo ^\
. Stessa bash e tutto, quindi l'unica differenza deve essere l'emulatore di terminale. Quindi ora la mia domanda diventa: come posso configurare gnome-terminal in modo che si comporti come la console virtuale sotto questo aspetto? Ho diff
gli output di stty -a
nella console virtuale e in gnome-terminal e, sebbene ci siano differenze, nulla sembra immediatamente rilevante (ad esempio, entrambi hanno quit = ^\;
).
AGGIORNAMENTO 2:
Un altro esperimento. Esegui semplicemente $ sleep 60
in gnome-terminal; premere ^\
e il segnale non viene rilevato. Ora esegui $ sleep 60
nella console virtuale; premere ^\
e il segnale viene catturato: il processo stampa Quit
ed esce. Ma ora esegui $ ping google.com
in gnome-terminal e premi ^\
: il segnale viene catturato e gestito come previsto. Quindi c'è qualcosa di strano in gnome-terminal tale che SIGQUIT può essere catturato da alcuni programmi, ma non da altri, anche se gli altri lo fanno quando vengono invocati dalla console virtuale. Forse dovrei semplicemente aggiornare il mio gnome-terminal.
Soluzione
Posso solo presumere che si trattasse di una sorta di bug in gnome-terminal 2.32.0;Da allora ho aggiornato a Ubuntu 11.04, con gnome-terminal 2.32.1 (e bash 4.2.8) e SIGQUIT è ora intrappolato come previsto.
Altri suggerimenti
Osservo lo stesso comportamento su Fedora 19 con XFCE: secondo ps s
, bash in xfce4-terminal ha SIGQUIT ignorato, l'esecuzione di yes >/dev/null &
e poi ps s
mostra che anche un sottoprocesso ha SIGQUIT ignorato.Quando (dallo stesso terminale) eseguo ssh localhost
, anche la shell nella sessione ssh ha SIGQUIT ignorato, ma yes >/dev/null &
no.
Dato il commento sopra che menziona gnome-terminal, immagino che il bug sia nella parte comune dei due terminali: la libreria vte
.Il mio è vte-0.28.2-9.fc19.x86_64
.