2011-03-15 3 views
31

Ci sono molti punti di uscita nel mio codice bash. Ho bisogno di fare un po 'ripulire il lavoro in uscita, così ho usato trappola per aggiungere una funzione di callback per l'uscita in questo modo:Come intercettare il codice di uscita nello script Bash

trap "mycleanup" EXIT 

Il problema è che ci sono diversi codici di uscita, ho bisogno di fare lavori di pulizia corrispondente. Posso ottenere il codice di uscita in mycleanup?

+0

trap 'foo' EXIT o trap 'foo' CHLD? –

risposta

31

Penso che sia possibile utilizzare $? per ottenere il codice di uscita.

+1

sì, è corretto. Grazie! – Dagang

+2

@Todd: Le variabili '$ BASH_COMMAND' e' $ BASH_LINENO' sono utili anche a volte. –

+4

@Todd, @bmk: non dimenticare che * qualsiasi * comando eseguito cambia il valore di $ ?; ad esempio, myCmdIWantToTest; echo $? ; myRC = $? ; ... ora myRC è la "verità" dell'eco $? cmd invocato. Se myCmdIWantToTest è terminato 'false', quel valore è perso. È meglio risparmiare $? a una variabile denominata separatamente che è unica. Usando exitCode = $? universalmente, puoi facilmente ereditare qualche altro cmd di exitCode (o più probabilmente da una sotto-shell (script)). Inoltre, non dimenticare che è OK test exit code come parte di un if; poi ; ... fi. Mi piace se myCmdIWantToTest; allora l'eco ha funzionato; altrimenti echo fallito; fi – shellter

25

La risposta accettata è fondamentalmente corretta, voglio solo chiarire le cose.

L'esempio seguente funziona bene:

#!/bin/bash 

cleanup() { 
    rv=$? 
    rm -rf "$tmpdir" 
    exit $rv 
} 

tmpdir="$(mktemp)" 
trap "cleanup" INT TERM EXIT 
# Do things... 

Ma bisogna essere più attenti se facendo pulizia in linea, senza funzione. Per esempio questo non funzionerà:

trap "rv=$?; rm -rf $tmpdir; exit $rv" INT TERM EXIT 

Invece si devono sfuggire alle $rv e $? variabili:

trap "rv=\$?; rm -rf $tmpdir; exit \$rv" INT TERM EXIT 

Si potrebbe anche voler fuggire $tmpdir, come otterrà valutata quando la linea trappola viene eseguito e se il valore tmpdir viene modificato in un secondo momento, questo non ti darà il comportamento previsto.

Modifica: utilizzare shellcheck per controllare gli script di bash e prestare attenzione a problemi di questo tipo.

2

ho trovato che è meglio per intrappolare uscita separata dalla trappola per altri segnali

script di test trappola Esempio ...

umask 77 
tmpfile=`tmpfile.$$` 
trap 'rm -f "$tmpfile"' EXIT 
trap 'exit 2' HUP INT QUIT TERM 

touch $tmpfile 
read -r input 

exit 10 

il file temporaneo viene ripulito. Il valore di uscita del file di 10 viene mantenuto! Gli interrupt generano un valore di uscita di 2

Fondamentalmente finché non si utilizza "esci" in una trappola EXIT, uscirà con il valore di uscita originale mantenuto.

A parte: notare la citazione nella trappola EXIT. Ciò mi consente di cambiare il file che deve essere ripulito durante la vita degli script. Spesso includo anche un test per l'esistenza di $ tmpfile varables, quindi non ho nemmeno bisogno di impostarlo all'inizio dello script.