Когда процесс прерывается сигналом, способным обрабатывать, например, SIGINT
или SIGTERM
он не обрабатывает сигнал, каким будет код выхода процесса?
Как насчет таких необработанных сигналов SIGKILL
?
Из того, что я могу сказать, уничтожение процесса с SIGINT
вероятным результатом приводит к коду выхода 130
, но будет ли это зависеть от реализации ядра или оболочки?
$ cat myScript
#!/bin/bash
sleep 5
$ ./myScript
<ctrl-c here>
$ echo $?
130
Я не уверен, как я буду проверять другие сигналы ...
$ ./myScript &
$ killall myScript
$ echo $?
0 # duh, that's the exit code of killall
$ killall -9 myScript
$ echo $?
0 # same problem
kill
signals
exit
exit-status
Кори Кляйн
источник
источник
killall myScript
работы, поэтому возвращение killall (а не сценария!) равно 0. Вы можете поместитьkill -x $$
[x, являющийся номером сигнала, и $$ обычно расширяется оболочкой до PID этого сценария (работает в sh, bash, ...)] внутри скрипта, а затем протестируйте ядро его выхода.&
). Отправьте сигнал из другого процесса оболочки (в другой терминал), после чего вы сможете использовать его$?
после завершения работы myScript.Ответы:
Процессы могут вызывать
_exit()
системный вызов (в Linux, см. Такжеexit_group()
) с целочисленным аргументом, чтобы сообщить код выхода своему родителю. Хотя это целое число, только 8 младших значащих битов доступны для родителя (исключение составляет использованиеwaitid()
или обработка SIGCHLD в родительском объекте для получения этого кода , но не в Linux).Родитель обычно делает
wait()
или,waitpid()
чтобы получить статус своего потомка как целое число (хотяwaitid()
может также использоваться несколько иная семантика).В Linux и большинстве Unix, если процесс завершается нормально, биты 8–15 этого номера состояния будут содержать код завершения, как передано
exit()
. Если нет, то 7 младших значащих битов (от 0 до 6) будут содержать номер сигнала, а бит 7 будет установлен, если ядро было сброшено.perl
«ы$?
к примеру содержит это число , как установленоwaitpid()
:Подобные Борну оболочки также делают состояние выхода последней команды запуска в своей собственной
$?
переменной. Тем не менее, он не содержит непосредственно число, возвращаемоеwaitpid()
, но преобразование на него, и это отличается между оболочками.Что общего между всеми оболочками, так это то, что они
$?
содержат младшие 8 бит кода выхода (переданного числаexit()
), если процесс завершился нормально.Отличие состоит в том, когда процесс завершается сигналом. Во всех случаях, и это требуется POSIX, число будет больше 128. POSIX не указывает, какое значение может быть. Однако на практике во всех известных мне борноподобных оболочках младшие 7 бит
$?
будут содержать номер сигнала. Но гдеn
номер сигнала,в золе, зш, пдкш, баш, скорлупа Борна,
$?
есть128 + n
. Что это означает, что в этих оболочках, если вы получаете$?
от129
, вы не знаете , является ли это потому , что процесс завершился сexit(129)
или он был убит по сигналу1
(HUP
в большинстве систем). Но логическое обоснование состоит в том, что оболочки, когда они действительно выходят из себя, по умолчанию возвращают статус завершения последней вышедшей команды. Удостоверьтесь, что$?
никогда не больше 255, что позволяет иметь постоянный статус выхода:ksh93
,$?
Является256 + n
. Это означает, что по значению$?
вы можете различить убитый и неубранный процесс. Более новые версииksh
, при выходе, если$?
было больше 255, убивают себя тем же сигналом, чтобы иметь возможность сообщить об одном и том же статусе выхода его родителю. Хотя это звучит как хорошая идея, это означает, чтоksh
будет генерироваться дополнительный дамп ядра (возможно, с перезаписью другого), если процесс был убит сигналом генерации ядра:Где можно даже сказать , что есть ошибка в том , что
ksh93
убивает себя , даже если$?
исходит отreturn 257
сделано с помощью функции:yash
,yash
предлагает компромисс. Это возвращается256 + 128 + n
. Это означает, что мы также можем различать завершенный процесс и процесс, завершившийся должным образом. И после выхода он сообщит128 + n
без необходимости самоубийства и побочных эффектов, которые он может иметь.Чтобы получить сигнал от значения
$?
, переносимым способом является использованиеkill -l
:(для переносимости, вы никогда не должны использовать номера сигналов, только имена сигналов)
На не-борнских фронтах:
csh
/tcsh
и тоfish
же самое, что и оболочка Bourne, за исключением того, что$status
вместо нее указан статус$?
(обратите внимание, чтоzsh
также устанавливается$status
совместимость сcsh
(в дополнение к$?
)).rc
: состояние выхода также в$status
состоянии, но когда убито сигналом, эта переменная содержит имя сигнала (например,sigterm
илиsigill+core
если ядро было сгенерировано) вместо числа, что является еще одним доказательством хорошего дизайна этой оболочки ,es
, статус выхода не является переменной. Если вы заботитесь об этом, вы запускаете команду как:который вернет число или
sigterm
илиsigsegv+core
как вrc
.Возможно, для полноты изложения, мы должны упомянуть массивы
zsh
's'$pipestatus
иbash
's',$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
для команды, не найденной или не исполняемой (или синтаксическая ошибка в исходном файле) ...источник
an exit code to their parent
иto get the *status* of their child
. Вы добавили акцент на «статус». Естьexit code
и*status*
то же самое? Случай да, каково происхождение наличия двух имен? Случай не такой, не могли бы вы дать определение / ссылку на статус?exit()
. Состояние выхода : число, полученное сwaitpid()
указанием кода выхода, номера сигнала и наличия сброса ядра. И число, которое некоторые оболочки делают доступным в одной из своих специальных переменных ($?
,$status
), которая является преобразованием состояния выхода таким образом, что оно содержит код выхода в случае нормального завершения, но также несет информацию о сигнале, если процесс был убит (этот также обычно называется статусом выхода ). Это все объясняется в моем ответе.> 128
часть: «Состояние завершения команды, которая завершилась, потому что она получила сигнал, должно быть сообщено как больше 128». pubs.opengroup.org/onlinepubs/9699919799/utilities/…efe764d811849b34eef24bfb14106f61@austingroupbugs.net
(от 2015-05-06) илиXref: news.gmane.org gmane.comp.standards.posix.austin.general:10726
Когда процесс завершается, он возвращает целочисленное значение операционной системе. В большинстве вариантов Unix это значение принимается по модулю 256: все, кроме младших битов, игнорируется. Статус дочернего процесса возвращается его родителю через 16-разрядное целое число, в котором
Статус возвращается
wait
системным вызовом или одним из его братьев и сестер. POSIX не определяет точную кодировку состояния выхода и номера сигнала; это только обеспечиваетСтрого говоря, нет никакого выхода кода , когда процесс был убит сигналом: что есть вместо того, чтобы есть выход состояние .
В сценарии оболочки состояние завершения команды сообщается через специальную переменную
$?
. Эта переменная кодирует статус выхода неоднозначно:$?
это его статус завершения .$?
в большинстве систем это 128 плюс номер сигнала. POSIX только мандаты, которые$?
больше 128 в этом случае; ksh93 добавляет 256 вместо 128. Я никогда не видел вариант Unix, который делал бы что-то кроме добавления константы к номеру сигнала.Таким образом, в сценарии оболочки вы не можете окончательно сказать, была ли команда уничтожена сигналом или завершилась с кодом состояния больше 128, кроме как с помощью ksh93. Очень редко программы выходят с кодами состояния больше 128, отчасти потому, что программисты избегают этого из-за
$?
неоднозначности.SIGINT - это сигнал 2 в большинстве вариантов Unix, поэтому он
$?
равен 128 + 2 = 130 для процесса, который был остановлен SIGINT. Вы увидите 129 для SIGHUP, 137 для SIGKILL и т. Д.источник
$?
это только для Bourne-подобных оболочек. Смотрите такжеyash
о другом (но все же POSIX) поведении. Также в соответствии с POSIX + XSI (Unix), akill -2 "$pid"
отправит процесс SIGINT, но фактический номер сигнала может не быть 2, так что $? не обязательно будет 128 + 2 (или 256 + 2 или 384 + 2), хотяkill -l "$?"
и вернетсяINT
, поэтому я бы посоветовал для переносимости не ссылаться на сами числа.Это зависит от вашей оболочки. На
bash(1)
странице man раздела SHELL GRAMMAR , подраздел Simple Commands :Поскольку
SIGINT
в вашей системе используется сигнал номер 2, возвращаемое значение равно 130, когда оно запускается под Bash.источник
signal(7)
страницу руководства .Кажется, стоит упомянуть, что SVr4 ввел waitid () в 1989 году, но пока ни одна важная программа не использует его. waitid () позволяет получить полные 32 бита из кода выхода ().
Около 2 месяцев назад я переписал часть ожидания / задания в командной оболочке Bourne, чтобы использовать waitid () вместо waitpid (). Это было сделано для того, чтобы снять ограничение, маскирующее код выхода с 0xFF.
Интерфейс waitid () намного чище, чем предыдущие реализации wait (), за исключением вызова cwait () из UNOS 1980 года.
Вам может быть интересно прочитать справочную страницу по адресу:
http://schillix.sourceforge.net/man/man1/bosh.1.html
и проверьте раздел «Подстановка параметров», который в данный момент начинается на стр. 8.
Новые переменные .sh. * Были введены для интерфейса waitid (). Этот интерфейс больше не имеет неоднозначных значений для чисел, известных как $? и сделать взаимодействие намного проще.
Обратите внимание, что вам нужно иметь POSIX-совместимый waitid (), чтобы иметь возможность использовать эту функцию, поэтому Mac OS X и Linux в настоящее время не предлагают этого, но waitid () эмулируется при вызове waitpid (), поэтому не POSIX-платформа, вы все равно получите только 8 бит из кода выхода.
Вкратце: .sh.status - это числовой код выхода, .sh.code - это числовая причина выхода.
Для лучшей переносимости, есть: .sh.codename для текстовой версии причины выхода, например, «DUMPED» и .sh.termsig, имя сингальса для сигнала, который завершил процесс.
Для лучшего использования есть два значения .sh.codename, не связанных с выходом: «NOEXEC» и «NOTFOUND», которые используются, когда программа вообще не может быть запущена.
FreeBSD устранила ошибку ядра waitid () в течение 20 часов после моего отчета, Linux еще не запустила их исправление. Я надеюсь, что через 26 лет после введения этой функции, которая сейчас есть в POSIX, все ОС скоро ее поддержат.
источник