I processi possono chiamare la chiamata di _exit()
sistema (su Linux, vedi anche exit_group()
) con un argomento intero per segnalare un codice di uscita al loro genitore. Sebbene sia un numero intero, solo i 8 bit meno significativi sono disponibili per il genitore (ad eccezione di quando si utilizza waitid()
o il gestore su SIGCHLD nel genitore per recuperare quel codice , sebbene non su Linux).
Il genitore farà tipicamente un wait()
o waitpid()
per ottenere lo stato del proprio figlio come intero (anche se waitid()
con semantica un po 'diversa può essere usato anche).
Su Linux e la maggior parte degli Unices, se il processo è terminato normalmente, i bit da 8 a 15 di quel numero di stato conterranno il codice di uscita passato a exit()
. In caso contrario, i 7 bit meno significativi (da 0 a 6) conterranno il numero del segnale e il bit 7 verrà impostato in caso di dump di un core.
perl
's $?
, ad esempio, contiene quel numero come set per waitpid()
:
$ perl -e 'system q(kill $$); printf "%04x\n", $?'
000f # killed by signal 15
$ perl -e 'system q(kill -ILL $$); printf "%04x\n", $?'
0084 # killed by signal 4 and core dumped
$ perl -e 'system q(exit $((0xabc))); printf "%04x\n", $?'
bc00 # terminated normally, 0xbc the lowest 8 bits of the status
Le shell tipo Bourne inoltre rendono lo stato di uscita dell'ultimo comando di esecuzione nella propria $?
variabile. Tuttavia, non contiene direttamente il numero restituito da waitpid()
, ma una trasformazione su di esso, ed è diverso tra le shell.
La cosa comune tra tutte le shell è che $?
contiene gli 8 bit più bassi del codice di uscita (il numero passato a exit()
) se il processo è terminato normalmente.
La differenza è quando il processo è terminato da un segnale. In tutti i casi, e ciò è richiesto da POSIX, il numero sarà maggiore di 128. POSIX non specifica quale possa essere il valore. In pratica, tuttavia, in tutte le shell tipo Bourne che conosco, i 7 bit più bassi $?
conterranno il numero del segnale. Ma dov'è n
il numero del segnale,
in cenere, zsh, pdksh, bash, la shell Bourne, $?
è 128 + n
. Ciò significa che in quei gusci, se si ottiene una $?
di 129
, non si sa se è perché il processo è terminato con exit(129)
o se sia stato ucciso dal segnale 1
( HUP
sulla maggior parte dei sistemi). Ma la logica è che le shell, quando escono da sole, restituiscono di default lo stato di uscita dell'ultimo comando uscito. Assicurandosi che $?
non sia mai maggiore di 255, ciò consente di avere uno stato di uscita coerente:
$ bash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
bash: line 1: 16720 Terminated sh -c "kill \$\$"
8f # 128 + 15
$ bash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?"
bash: line 1: 16726 Terminated sh -c "kill \$\$"
8f # here that 0x8f is from a exit(143) done by bash. Though it's
# not from a killed process, that does tell us that probably
# something was killed by a SIGTERM
ksh93
, $?
È 256 + n
. Ciò significa che da un valore di $?
te puoi distinguere tra un processo ucciso e non ucciso. Versioni più recenti di ksh
, all'uscita, se $?
maggiore di 255, si uccide con lo stesso segnale per poter riportare lo stesso stato di uscita al suo genitore. Anche se sembra una buona idea, ciò significa che ksh
genererà un dump core aggiuntivo (potenzialmente sovrascrivendo l'altro) se il processo è stato interrotto da un segnale di generazione del core:
$ ksh -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
ksh: 16828: Terminated
10f # 256 + 15
$ ksh -c 'sh -c "kill -ILL \$\$"; exit'; printf '%x\n' "$?"
ksh: 16816: Illegal instruction(coredump)
Illegal instruction(coredump)
104 # 256 + 15, ksh did indeed kill itself so as to report the same
# exit status as sh. Older versions of `ksh93` would have returned
# 4 instead.
Dove si potrebbe anche dire che c'è un bug è che si ksh93
uccide anche se $?
deriva return 257
da una funzione eseguita:
$ ksh -c 'f() { return "$1"; }; f 257; exit'
zsh: hangup ksh -c 'f() { return "$1"; }; f 257; exit'
# ksh kills itself with a SIGHUP so as to report a 257 exit status
# to its parent
yash
. yash
offre un compromesso. Ritorna 256 + 128 + n
. Ciò significa che possiamo anche distinguere tra un processo interrotto e uno che è terminato correttamente. E all'uscita, riferirà 128 + n
senza suicidarsi e con gli effetti collaterali che può avere.
$ yash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
18f # 256 + 128 + 15
$ yash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?"
8f # that's from a exit(143), yash was not killed
Per ottenere il segnale dal valore di $?
, il modo portatile è usare kill -l
:
$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM
(per la portabilità, non utilizzare mai numeri di segnale, solo nomi di segnali)
Sui fronti non Bourne:
csh
/ tcsh
e lo fish
stesso della shell Bourne tranne per il fatto che lo stato è in $status
invece di $?
(nota che zsh
imposta anche $status
per la compatibilità con csh
(oltre a $?
)).
rc
: lo stato di uscita è $status
anche presente, ma quando viene ucciso da un segnale, quella variabile contiene il nome del segnale (come sigterm
o sigill+core
se è stato generato un core) anziché un numero, che è ancora un'altra prova del buon design di quella shell .
es
. lo stato di uscita non è una variabile. Se ti interessa, esegui il comando come:
status = <={cmd}
che restituirà un numero sigterm
o sigsegv+core
simili in rc
.
Forse per completezza, dobbiamo menzionare zsh
's $pipestatus
e bash
' s $PIPESTATUS
array che contengono lo stato di uscita dei componenti dell'ultima pipeline.
E anche per completezza, quando si tratta di funzioni shell e file di origine, le funzioni predefinite ritornano con lo stato di uscita dell'ultima esecuzione del comando, ma possono anche impostare esplicitamente uno stato di ritorno con l' return
integrato. E vediamo alcune differenze qui:
bash
e mksh
(da R41, una regressione ^ Wchange apparentemente introdotta intenzionalmente ) troncerà il numero (positivo o negativo) a 8 bit. Ad esempio, return 1234
verrà impostato $?
su 210
, return -- -1
impostato $?
su 255.
zsh
e pdksh
(e derivati diversi da mksh
) consentire qualsiasi numero intero decimale a 32 bit con segno (da -2 31 a 2 31 -1) (e troncare il numero a 32 bit).
ash
e yash
consentire qualsiasi numero intero positivo compreso tra 0 e 2 31 -1 e restituire un errore per qualsiasi numero.
ksh93
per return 0
di return 320
set $?
come è, ma per tutto il resto, Tronca a 8 bit. Attenzione come già detto che restituire un numero compreso tra 256 e 320 potrebbe causare ksh
l'uccisione di se stesso all'uscita.
rc
e es
consentire la restituzione di qualsiasi elenco uniforme.
Si noti inoltre che alcune shell usano anche valori speciali di $?
/ $status
per segnalare alcune condizioni di errore che non sono lo stato di uscita di un processo, come 127
o 126
per comando non trovato o non eseguibile (o errore di sintassi in un file di origine) ...
killall myScript
lavori, quindi il ritorno del killall (e non dello script!) è 0. Puoi posizionare unkill -x $$
[x essendo il numero del segnale e $$ solitamente espanso dalla shell al PID di quello script (funziona in sh, bash, ...)] all'interno dello script e quindi prova qual era il suo nucleo di uscita.