Bash scripting - segnali: differenze tra le versioni

→‎Cattura dei segnali: aggiunti esempi
(- template "Versioni compatibili")
(→‎Cattura dei segnali: aggiunti esempi)
Riga 31: Riga 31:
* se la stringa è vuota, i segnali verranno ignorati;
* se la stringa è vuota, i segnali verranno ignorati;
* se la stringa è il nome di una funzione, verrà eseguita ogni volta che uno dei segnali viene ricevuto. L'azione normale è sovrascritta, quindi se è necessario preservarla dopo la funzione, dovrà occuparsene la funzione stessa (per esempio di uscire con <code>exit</code> dopo aver effettuato la pulizia);
* se la stringa è il nome di una funzione, verrà eseguita ogni volta che uno dei segnali viene ricevuto. L'azione normale è sovrascritta, quindi se è necessario preservarla dopo la funzione, dovrà occuparsene la funzione stessa (per esempio di uscire con <code>exit</code> dopo aver effettuato la pulizia);
* il segnale può essere '''EXIT''', che ha significato solo per questa istruzione, in tal caso la funzione sarà eseguita alla fine dello script, che può essere causata anche da segnali (con l'unica eccezione di KILL), purché lo script non termini con un <code>exec</code> seguito da un eseguibile.
* il segnale può essere '''EXIT''', che ha significato solo per questa istruzione, in tal caso la funzione sarà eseguita alla fine dello script, che può essere causata anche da segnali (con l'unica eccezione di KILL), purché lo script non termini con un <code>exec</code> seguito da un eseguibile. In ''POSIX'' invece la funzione sarebbe eseguita soltanto in caso di uscita normale dello script. In ogni caso la terminazione dello script non è annullata definendo un azione, come invece per i veri segnali.


{{Warningbox | Al posto di 'stringa' nell'istruzione <code>trap</code> può esserci un qualsiasi comando, ma si consiglia l'uso di una funzione sia per chiarezza del codice, sia soprattutto per evitare la doppia interpretazione con possibili espansioni in fase di definizione di <code>trap</code> prima e di esecuzione del comando poi. Un uso diverso ha la stessa pericolosità di <code>eval</code>, e può portare a <code>code injection</code> e <code>privilege escalation</code>.}}
{{Warningbox | Al posto di 'stringa' nell'istruzione <code>trap</code> può esserci un qualsiasi comando, ma si consiglia l'uso di una funzione sia per chiarezza del codice, sia soprattutto per evitare la doppia interpretazione con possibili espansioni in fase di definizione di <code>trap</code> prima e di esecuzione del comando poi. Un uso diverso ha la stessa pericolosità di <code>eval</code>, e può portare a <code>code injection</code> e <code>privilege escalation</code>.}}


Un esempio classico di <code>trap</code>:
In caso di esecuzione di una subshell le azioni da intraprendere in seguito alla ricezione di un segnale vengono reimpostate al loro valore di default, ma i segnali ignorati continuano a restare ignorati.
 
===Esempi===
* Ignora i segnali di terminazione:
<pre>
trap '' INT HUP QUIT TERM  # segnali standard di terminazione
</pre>
Nota che '''KILL''' non può essere ignorato e nemmeno catturato, quindi in genere è sconsigliabile non prevedere una terminazione non brutale attraverso un segnale.
 
* Ignora il segnale HUP (equivalente a eseguire lo script con il comando <code>nohup</code>), per permettere di avviare lo script in background e sopravvivere anche dopo la chiusura del terminale associato:
<pre>
trap '' HUP
</pre>
 
* Esegue una funzione (<code>interrupt</code>) alla ricezione di tutti i segnali (standard) di terminazione, prima di uscire:
<pre>
interrupt () {
    # fai qualcosa
    ...
    exit 127 # chiusura esplicita NECESSARIA
            # perché l'azione di default è sovrascritta
}
 
...
 
# esegue interrupt se uno dei segnali è ricevuto
# e poi esci (perché specificato in interrupt!)
trap 'interrupt' INT HUP QUIT TERM
 
...
 
exit 0      # non esegue interrupt
</pre>
 
* Ignora solo i segnali di terminazione da tastiera, ma esegue una funzione (<code>interrupt</code>) con il segnale standard di terminazione:
<pre>
interrupt () {
    # fai qualcosa
    ...
    exit 127 # chiusura esplicita NECESSARIA
            # perché l'azione di default è sovrascritta
}
 
# ignora terminazione da tastiera
trap '' INT QUIT
 
# gestisci altri segnali di terminazione
trap 'interrupt' HUP TERM
</pre>
 
* Esegue una funzione di pulizia (<code>clean</code>) al termine dello script:
<pre>
<pre>
clean () {
clean () {
     # funzione di pulizia
     # funzione di pulizia
     ...
     ...
    # NOTA: niente exit finale per evitare loop infinito
    # infatti è già richiamata da trap ... EXIT!
}
}


trap 'clean' EXIT   # la funzione clean è eseguita se si riceve un segnale di terminazione
...
 
# la funzione clean è eseguita alla terminazione
trap 'clean' EXIT
 
# esci (codice 127), eseguendo clean,  alla ricezione di questi segnali
# non è necessario in bash, perché è implicito
trap 'exit 127' INT HUP QUIT TERM
 
...
...
if comando; then
if comando; then
Riga 50: Riga 110:
exit 0              # clean è eseguita anche con exit
exit 0              # clean è eseguita anche con exit
</pre>
</pre>
In caso di esecuzione di una subshell le azioni da intraprendere in seguito alla ricezione di un segnale vengono reimpostate al loro valore di default, ma i segnali ignorati continuano a restare ignorati.


{{Autori
{{Autori
|Autore=[[Utente:HAL 9000|HAL 9000]] 13:10, 22 lug 2014 (CEST)
|Autore=[[Utente:HAL 9000|HAL 9000]] 19:01, 22 lug 2014 (CEST)
}}
}}


[[Categoria:Bash]][[Categoria:Bash_Scripting]]
[[Categoria:Bash]][[Categoria:Bash_Scripting]]
3 581

contributi