Procesy mogą wywoływać wywołanie _exit()
systemowe (w systemie Linux, patrz także exit_group()
) z argumentem liczby całkowitej, aby zgłosić kod wyjścia do ich rodzica. Chociaż jest to liczba całkowita, tylko 8 najmniej znaczących bitów jest dostępnych dla rodzica (wyjątek stanowi to podczas używania waitid()
lub obsługi SIGCHLD w rodzicu w celu pobrania tego kodu , choć nie w Linuksie).
Rodzic zwykle robi a wait()
lub, waitpid()
aby uzyskać status swojego dziecka jako liczbę całkowitą (chociaż waitid()
można użyć również nieco innej semantyki).
W systemie Linux i większości Uniksów, jeśli proces zakończy się normalnie, bity od 8 do 15 tego numeru statusu będą zawierały kod wyjścia, który został przekazany exit()
. Jeśli nie, to 7 najmniej znaczących bitów (od 0 do 6) będzie zawierało numer sygnału, a bit 7 zostanie ustawiony, jeśli rdzeń został zrzucony.
perl
jest $?
, na przykład, że zawiera szereg określonych przez 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
Powłoki podobne do Bourne'a również ustawiają status wyjścia ostatniego polecenia uruchomienia we własnej $?
zmiennej. Jednak nie zawiera bezpośrednio liczby zwróconej przez waitpid()
, ale transformację i różni się między powłokami.
Wspólne dla wszystkich powłok jest to, że $?
zawiera najmniej 8 bitów kodu wyjścia (liczby przekazanej do exit()
), jeśli proces zakończy się normalnie.
Różni się to, gdy proces kończy się sygnałem. We wszystkich przypadkach, a jest to wymagane przez POSIX, liczba będzie większa niż 128. POSIX nie określa, jaka może być wartość. W praktyce jednak we wszystkich znanych mi powłokach Bourne'a 7 najniższych bitów $?
będzie zawierało liczbę sygnałów. Ale gdzie n
jest numer sygnału,
w ash, zsh, pdksh, bash, powłoka Bourne'a $?
jest 128 + n
. Co to znaczy, że w tych pocisków, jeśli masz $?
z 129
, nie wiem, czy to dlatego, że proces zakończył działanie exit(129)
, czy też został zabity sygnałem 1
( HUP
w większości systemów). Ale uzasadnieniem jest to, że powłoki, gdy same się kończą, domyślnie zwracają status wyjścia ostatnio zakończonej komendy. Upewniając się, że $?
nigdy nie jest większy niż 255, pozwala to uzyskać spójny status wyjścia:
$ 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
, $?
jest 256 + n
. Oznacza to, że od wartości $?
możesz rozróżnić proces zabity i nie zabity. Nowsze wersje ksh
, przy wyjściu, jeśli $?
były większe niż 255, zabijają się tym samym sygnałem, aby móc zgłosić ten sam status wyjścia rodzicowi. Chociaż wydaje się to dobrym pomysłem, oznacza to, że ksh
wygeneruje dodatkowy zrzut rdzenia (potencjalnie nadpisujący drugi), jeśli proces zostanie zabity przez sygnał generujący rdzeń:
$ 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.
Można nawet powiedzieć, że jest błąd, który ksh93
zabija się, nawet jeśli $?
pochodzi od funkcji return 257
wykonanej przez:
$ 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
oferuje kompromis. Powraca 256 + 128 + n
. Oznacza to, że możemy również odróżnić zabity proces od tego, który zakończył się prawidłowo. A po wyjściu zgłosi się 128 + n
bez samobójstwa i skutków ubocznych, jakie może mieć.
$ 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
Aby uzyskać sygnał z wartości $?
, przenośnym sposobem jest użycie kill -l
:
$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM
(ze względu na przenośność nigdy nie należy używać numerów sygnałów, a jedynie nazw sygnałów)
Na frontach innych niż Bourne:
csh
/ tcsh
i to fish
samo co powłoka Bourne'a, z tym wyjątkiem, że status jest $status
zamiast $?
(należy pamiętać, że zsh
ustawia się również $status
dla zgodności z csh
(oprócz $?
)).
rc
: status wyjścia $status
również jest, ale gdy zabije go sygnał, zmienna ta zawiera nazwę sygnału (jak sigterm
lub sigill+core
jeśli rdzeń został wygenerowany) zamiast liczby, co jest kolejnym dowodem dobrego projektu tej powłoki .
es
. status wyjścia nie jest zmienną. Jeśli zależy Ci na tym, uruchom polecenie jako:
status = <={cmd}
która zwróci liczbę sigterm
lub sigsegv+core
jak w rc
.
Może pod względem kompletności, powinniśmy wspomnieć zsh
„s $pipestatus
i bash
” s $PIPESTATUS
tablice, które zawierają kod zakończenia elementów ostatniej rurociągu.
A także dla kompletności, jeśli chodzi o funkcje powłoki i pliki źródłowe, domyślnie funkcje zwracają ze statusem zakończenia ostatniego uruchomienia polecenia, ale mogą również ustawić jawnie status powrotu za pomocą return
wbudowanego. Widzimy tutaj pewne różnice:
bash
i mksh
(od R41 regresja ^ Witch najwyraźniej wprowadzona umyślnie ) skróci liczbę (dodatnią lub ujemną) do 8 bitów. Na przykład return 1234
ustawimy $?
na 210
, return -- -1
ustawimy $?
na 255.
zsh
oraz pdksh
(i pochodne inne niż mksh
) pozwalają na każdą 32-bitową liczbę całkowitą ze znakiem (-2 31 do 2 31 -1) (i skracają liczbę do 32 bitów ).
ash
i yash
zezwól na dowolną liczbę całkowitą dodatnią od 0 do 2 31 -1 i zwróć błąd dla dowolnej liczby z tego.
ksh93
w return 0
celu return 320
ustawienia $?
w takim stanie, ale nic innego, obcina do 8 bitów. Uważaj, jak już wspomniano, że zwrócenie liczby między 256 a 320 może spowodować ksh
samobójstwo przy wyjściu.
rc
i es
zezwalaj na zwracanie dowolnych nawet list
Należy również pamiętać, że niektóre powłoki również użyć specjalnych wartości $?
/ $status
zgłosić pewne warunki błędów, które nie są kod zakończenia procesu, jak 127
i 126
na polecenie nie znaleziono lub nie wykonywalny (lub błąd składni w pliku) pochodzących ...
killall myScript
prace, stąd zwrócenie killall (a nie skryptu!) wynosi 0. Możesz umieścićkill -x $$
[x będący liczbą sygnału, a $$ zwykle rozszerzane przez powłokę do PID tego skryptu (działa w sh, bash, ...)] w skrypcie, a następnie przetestuj, jaki był jego rdzeń wyjściowy.