Процеси можуть викликати _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, ...)] всередині сценарію, а потім перевірити те, що було його вихідним ядром.