Když je proces zabit signálem, který lze ovládat, jako je SIGINT
nebo SIGTERM
ale nezpracovává signál, jaký bude výstupní kód procesu?
A co pro nezvládnutelné signály jako SIGKILL
?
Z toho, co vím, zabíjení procesu pomocí SIGINT
pravděpodobně vyústí v ukončovací kód 130
, ale lišilo by se to podle implementace jádra nebo shellu?
$ cat myScript
#!/bin/bash
sleep 5
$ ./myScript
<ctrl-c here>
$ echo $?
130
Nejsem si jistý, jak bych otestoval ostatní signály…
$ ./myScript &
$ killall myScript
$ echo $?
0 # duh, that's the exit code of killall
$ killall -9 myScript
$ echo $?
0 # same problem
Přijatá odpověď:
Procesy mohou volat _exit()
systémové volání (v Linuxu viz také exit_group()
) s celočíselným argumentem pro nahlášení výstupního kódu jejich rodiči. Ačkoli se jedná o celé číslo, nadřazenému prvku je k dispozici pouze 8 nejméně významných bitů (výjimkou je použití waitid()
nebo handler na SIGCHLD v nadřazeném nástroji pro načtení tohoto kódu, i když ne na Linuxu).
Rodič obvykle provede wait()
nebo waitpid()
získat stav jejich potomka jako celé číslo (ačkoli waitid()
s poněkud odlišnou sémantikou lze také použít).
V Linuxu a většině Unices, pokud byl proces ukončen normálně, bity 8 až 15 tohoto stavu number bude obsahovat návratový kód předaný do exit()
. Pokud ne, pak 7 nejméně významných bitů (0 až 6) bude obsahovat číslo signálu a bit 7 bude nastaven, pokud bylo jádro vyhozeno.
perl
's $?
například obsahuje toto číslo nastavené pomocí waitpid()
:
$ perl -e 'system q(kill $$); printf "%04xn", $?'
000f # killed by signal 15
$ perl -e 'system q(kill -ILL $$); printf "%04xn", $?'
0084 # killed by signal 4 and core dumped
$ perl -e 'system q(exit $((0xabc))); printf "%04xn", $?'
bc00 # terminated normally, 0xbc the lowest 8 bits of the status
Shelly podobné Bourneovi také vytvářejí stav ukončení posledního spuštěného příkazu ve svém vlastním $?
variabilní. Neobsahuje však přímo číslo vrácené funkcí waitpid()
, ale je na něm transformace a mezi shelly je to jiné.
Co je společné mezi všemi shelly, je to, že $?
obsahuje nejnižších 8 bitů výstupního kódu (číslo předané do exit()
), pokud byl proces ukončen normálně.
Kde se liší je, když je proces ukončen signálem. Ve všech případech, a to vyžaduje POSIX, bude číslo větší než 128. POSIX nespecifikuje, jaká hodnota může být. V praxi však ve všech shellech podobných Bourneovi, které znám, nejnižších 7 bitů $?
bude obsahovat číslo signálu. Ale kde n
je číslo signálu,
-
v ash, zsh, pdksh, bash, Bourne shell,
$?
je128 + n
. Co to znamená, že v těchto shellech, pokud dostanete$?
z129
, nevíte, zda je to tím, že proces skončil sexit(129)
nebo zda byl zabit signálem1
(HUP
na většině systémů). Důvodem však je, že když se shelly samy ukončí, ve výchozím nastavení vrátí stav ukončení posledního ukončeného příkazu. Ujistěte se, že$?
není nikdy větší než 255, což umožňuje mít konzistentní stav ukončení:$ bash -c 'sh -c "kill $$"; printf "%xn" "$?"' bash: line 1: 16720 Terminated sh -c "kill $$" 8f # 128 + 15 $ bash -c 'sh -c "kill $$"; exit'; printf '%xn' "$?" 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
,$?
je256 + n
. To znamená, že z hodnoty$?
můžete rozlišovat mezi zabitým a neukončeným procesem. Novější verzeksh
, při ukončení, pokud$?
byl větší než 255, zabije se stejným signálem, aby mohl nahlásit stejný stav ukončení svému nadřazenému. I když to zní jako dobrý nápad, znamená to, žeksh
vygeneruje další výpis jádra (potenciálně přepíše druhý), pokud byl proces zabit signálem generujícím jádro:$ ksh -c 'sh -c "kill $$"; printf "%xn" "$?"' ksh: 16828: Terminated 10f # 256 + 15 $ ksh -c 'sh -c "kill -ILL $$"; exit'; printf '%xn' "$?" 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.
Tam, kde byste dokonce mohli říci, že existuje chyba, je
ksh93
zabije se, i když$?
pochází zreturn 257
provedená funkcí:$ 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
nabízí kompromis. Vrátí256 + 128 + n
. To znamená, že můžeme také rozlišovat mezi zabitým procesem a procesem, který byl ukončen správně. A při ukončení ohlásí128 + n
aniž byste museli spáchat sebevraždu a vedlejší účinky, které to může mít.$ yash -c 'sh -c "kill $$"; printf "%xn" "$?"' 18f # 256 + 128 + 15 $ yash -c 'sh -c "kill $$"; exit'; printf '%xn' "$?" 8f # that's from a exit(143), yash was not killed
Chcete-li získat signál z hodnoty $?
, přenosný způsob je použít kill -l
:
$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM
(kvůli přenositelnosti byste nikdy neměli používat čísla signálů, pouze názvy signálů)
Související:Zálohy na úrovni bajtů versus zálohy na úrovni souborů?Na frontách mimo Bourne:
csh
/tcsh
afish
stejný jako Bourne shell kromě toho, že stav je v$status
místo$?
(všimněte si, žezsh
také nastaví$status
kvůli kompatibilitě scsh
(kromě$?
)).rc
:stav ukončení je v$status
také, ale když je zabit signálem, tato proměnná obsahuje název signálu (jakosigterm
nebosigill+core
pokud bylo vygenerováno jádro) místo čísla, což je dalším důkazem dobrého návrhu tohoto shellu.-
es
. výstupní stav není proměnná. Pokud vám na tom záleží, spusťte příkaz jako:status = <={cmd}
což vrátí číslo nebo
sigterm
nebosigsegv+core
jako vrc
.
Možná bychom pro úplnost měli zmínit zsh
's $pipestatus
a bash
's $PIPESTATUS
pole, která obsahují stav ukončení komponent posledního potrubí.
A také pro úplnost, pokud jde o funkce shellu a zdrojové soubory, ve výchozím nastavení se funkce vracejí se stavem ukončení posledního spuštění příkazu, ale mohou také nastavit návratový stav explicitně pomocí return
vestavěný. A zde vidíme určité rozdíly:
bash
amksh
(od R41, regrese^Wchange zjevně zavedená záměrně) zkrátí číslo (kladné nebo záporné) na 8 bitů. Napříkladreturn 1234
nastaví$?
na210
,return -- -1
nastaví$?
na 255.zsh
apdksh
(a deriváty jiné nežmksh
) povolit libovolné 32bitové dekadické celé číslo se znaménkem (-2 až 2-1) (a zkrátit číslo na 32 bitů).ash
ayash
povolit libovolné kladné celé číslo od 0 do 2-1 a vrátit chybu pro jakékoli z nich.ksh93
proreturn 0
return 320
nastavit$?
jak je, ale pro cokoliv jiného, zkrátit na 8 bitů. Pozor, jak již bylo zmíněno, vrácení čísla mezi 256 a 320 může způsobitksh
zabít se při odchodu.rc
aes
umožňují vrátit cokoli, dokonce i seznamy.
Všimněte si také, že některé shelly také používají speciální hodnoty $?
/$status
hlásit některé chybové stavy, které nejsou stavem ukončení procesu, například 127
nebo 126
pro příkaz nenalezen nebo nespustitelný (nebo chyba syntaxe ve zdrojovém souboru)…