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(HUPna 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, žekshvygeneruje 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
ksh93zabije se, i když$?pochází zreturn 257provedená 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.yashnabí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 + naniž 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/tcshafishstejný jako Bourne shell kromě toho, že stav je v$statusmísto$?(všimněte si, žezshtaké nastaví$statuskvůli kompatibilitě scsh(kromě$?)).rc:stav ukončení je v$statustaké, ale když je zabit signálem, tato proměnná obsahuje název signálu (jakosigtermnebosigill+corepokud 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
sigtermnebosigsegv+corejako 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:
bashamksh(od R41, regrese^Wchange zjevně zavedená záměrně) zkrátí číslo (kladné nebo záporné) na 8 bitů. Napříkladreturn 1234nastaví$?na210,return -- -1nastaví$?na 255.zshapdksh(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ů).ashayashpovolit libovolné kladné celé číslo od 0 do 2-1 a vrátit chybu pro jakékoli z nich.ksh93proreturn 0return 320nastavit$?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ůsobitkshzabít se při odchodu.rcaesumožň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)…