Процеси можуть викликати _exit()
системний виклик (в Linux, див. Також exit_group()
) з цілим аргументом, щоб повідомити про вихідний код своєму батькові. Хоча це ціле число, для батьків є лише 8 найменш значущих бітів (виняток - при використанні waitid()
або обробці на SIGCHLD у батьків, щоб отримати цей код , хоча не в Linux).
Батько, як правило, виконує wait()
або waitpid()
отримує статус своєї дитини як ціле число (хоча waitid()
з дещо різною семантикою також можна використовувати).
В Linux і більшість Юніксів якщо процес припиняється , як правило, бітам з 8 по 15 з цього стану числа буде містити код завершення , як передається exit()
. Якщо ні, то 7 найменш значущих бітів (0 до 6) будуть містити число сигналу, а біт 7 буде встановлений, якщо ядро було скинуто.
perl
«И $?
, наприклад , містить це число , як встановлено 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
Оболонки, подібні до Борна, також вносять статус виходу останньої команди запуску у власну $?
змінну. Однак воно не містить прямо повернене число waitpid()
, а перетворення на ньому, і воно різне між оболонками.
Що є загальним для всіх оболонок, це те, що вони $?
містять найнижчі 8 біт коду виходу (число, передане exit()
), якщо процес закінчується нормально.
Де вона відрізняється, коли процес припиняється сигналом. У всіх випадках, а це вимагає POSIX, число буде перевищувати 128. POSIX не вказує, яке значення може бути. На практиці, однак у всіх відомих мені оболонках Борна, найнижчі 7 біт $?
містять номер сигналу. Але де n
номер сигналу,
in ash, zsh, pdksh, bash, оболонка Bourne, $?
є 128 + n
. Що це означає, що в цих оболонках, якщо ви отримуєте $?
від 129
, ви не знаєте , чи є це тому , що процес завершився з exit(129)
або він був убитий за сигналом 1
( HUP
в більшості систем). Але обґрунтуванням є те, що оболонки, коли вони самі виходять, за замовчуванням повертають статус виходу останньої випущеної команди. Переконайтесь, що $?
він ніколи не перевищує 255, що дозволяє мати постійний статус виходу:
$ 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
. Це означає, що за значенням $?
ви можете розмежовувати процес вбитого та не вбитого. Більш новіші версії ksh
, після виходу, якщо їх $?
було більше 255, вбиває себе тим самим сигналом, щоб мати можливість повідомляти про той самий статус виходу своєму батькові. Хоча це звучить як гарна ідея, це означає, що ksh
генерує додатковий дамп ядра (потенційно перезаписуючи інший), якщо процес був убитий ядром, що генерує сигнал:
$ 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.
Де ви навіть можете сказати, що виникла помилка - це те, що ksh93
вбиває себе, навіть якщо $?
походить від return 257
виконаної функції:
$ 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
пропонує компроміс. Це повертається 256 + 128 + n
. Це означає, що ми можемо також розмежовувати процес вбитого та той, що закінчився належним чином. А після виходу він повідомить про себе, 128 + n
не потребуючи самогубства та побічних ефектів, які він може мати.
$ 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
Для отримання сигналу від значення $?
портативного способу є використання kill -l
:
$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM
(для портативності ніколи не слід використовувати сигнальні номери, а лише імена сигналів)
На фронтах, що не є Борном:
csh
/ tcsh
і те fish
саме, що оболонка Bourne, за винятком того, що статус $status
замість $?
(зауважте, що zsh
також встановлено $status
сумісність із csh
(на додаток до $?
)).
rc
: статус виходу також є $status
, але коли його вбиває сигнал, ця змінна містить ім'я сигналу (як-от sigterm
або, sigill+core
якщо було створено ядро) замість числа, що є ще одним підтвердженням хорошої конструкції цієї оболонки .
es
. статус виходу не є змінною. Якщо ви дбаєте про нього, ви запускаєте команду як:
status = <={cmd}
який поверне номер або sigterm
або sigsegv+core
як у rc
.
Можливо, для повноти слід згадати масиви zsh
's $pipestatus
і bash
', $PIPESTATUS
які містять статус виходу компонентів останнього трубопроводу.
А також для повноти, якщо мова йде про функції оболонки та джерела файлів, за замовчуванням функції повертаються зі статусом виходу останнього запуску команди, але також можуть встановлювати статус повернення явно за допомогою return
вбудованого. І тут ми бачимо деякі відмінності:
bash
і mksh
(оскільки R41, регресія ^ Wchange, очевидно, введена навмисно ), скоротить число (позитивне чи негативне) до 8 біт. Так, наприклад , return 1234
буде встановлений $?
в 210
, return -- -1
буде встановлено $?
255.
zsh
і pdksh
(та похідні, крім mksh
) дозволяють будь-якому підписаному 32-бітовому десятковому цілому числу (-2 31 до 2 31 -1) (і усікають число до 32 біт ).
ash
і yash
дозволити будь-яке додатне ціле число від 0 до 2 31 -1 і повернути помилку для будь-якого числа із цього.
ksh93
для , return 0
щоб return 320
встановити , $?
як є, але для чого - небудь ще, вкоротити до 8 біт. Остерігайтеся, як уже згадувалося, що повернення числа між 256 і 320 може призвести ksh
до вбивства при виході.
rc
і es
дозволяти повертати що-небудь навіть списки.
Також зауважте, що деякі оболонки також використовують спеціальні значення $?
/, $status
щоб повідомити про деякі умови помилок, які не є статусом виходу з процесу, наприклад, 127
або 126
для команди, яку не знайдено або не виконується (або синтаксична помилка у файлі, що розміщується) ...
killall myScript
роботи, отже, повернення killall (а не сценарію!) дорівнює 0. Ви можете розміститиkill -x $$
[x - номер сигналу, і $$ зазвичай розширюється оболонкою до PID цього сценарію (працює в sh, bash, ...)] всередині сценарію, а потім перевірити те, що було його вихідним ядром.