Недавно я наткнулся на этот список кодов выхода со специальными значениями из расширенного руководства по написанию сценариев. Они ссылаются на эти коды как зарезервированные и рекомендуют следующее:
В соответствии с приведенной выше таблицей коды выхода 1-2, 126-165 и 255 имеют специальные значения, и поэтому их следует избегать для указанных пользователем параметров выхода.
Некоторое время назад я написал скрипт, который использовал следующие коды состояния выхода:
- 0 - успех
- 1 - неверное имя хоста
- 2 - указаны неверные аргументы
- 3 - недостаточные права пользователя
Когда я писал сценарий, я не знал о каких-либо специальных кодах выхода, поэтому я просто начал с 1 для первого условия ошибки и увеличивал состояние выхода для каждого последующего типа ошибки.
Я написал скрипт с намерением, чтобы на более позднем этапе он мог быть вызван другими скриптами (которые могли проверять ненулевые коды выхода). Я на самом деле еще не сделал этого; до сих пор я запускал сценарий только из своей интерактивной оболочки (Bash), и мне было интересно, какие проблемы могут возникнуть из-за использования моих пользовательских кодов выхода. Насколько актуальна / важна рекомендация из Расширенного руководства по написанию сценариев?
Я не смог найти никаких подтверждающих советов в документации Bash; его раздел « Статус выхода» просто перечисляет коды выхода, используемые Bash, но не утверждает, что какой-либо из них зарезервирован, или не рекомендует использовать их для своих собственных скриптов / программ.
источник
Ответы:
Было несколько попыток стандартизировать значения кодов завершения процесса. Помимо того, что вы упомянули, я знаю:
BSD имеют
sysexits.h
значения для значений от 64 и выше.В
grep
документах GNU код выхода 0 означает, что было найдено хотя бы одно совпадение, 1 означает, что совпадений не найдено, а 2 означает ошибку ввода-вывода; это соглашение, очевидно, также полезно для других программ, для которых различие между «ничего не пошло не так, но я ничего не нашел» и «произошла ошибка ввода-вывода» имеет смысл.Многие реализации функции библиотеки C
system
используют код завершения 127, чтобы указать, что программа не существует или не удалось запустить.В Windows
NTSTATUS
коды (которые неудобно разбросаны по всему 32-битному пространству чисел) могут использоваться в качестве кодов выхода, особенно тех, которые указывают, что процесс был прерван из-за катастрофического неправильного поведения (например,STATUS_STACK_OVERFLOW
).Вы не можете рассчитывать на какую-либо конкретную программу, выполняющую какое-либо конкретное из этих соглашений. Единственное надежное правило заключается в том, что код выхода 0 - это успех, а все остальное - своего рода сбой. (Обратите внимание , что C89 - х
EXIT_SUCCESS
это не гарантированно иметь нулевое значение, однако,exit(0)
требуется , чтобы вести себя так жеexit(EXIT_SUCCESS)
. Даже если значения не совпадают)источник
Никакой код выхода не имеет специального значения, но значение
$?
может иметь особое значение.Проблема в том, как Bourne Shell и ksh93 обрабатывают и пересылают коды выхода и ситуации ошибок в переменную оболочки
$?
. В отличие от того, что вы перечисляете, только следующие значения$?
имеют особое значение:Кроме того, существует неопределенный диапазон
$?
кодов оболочки и платформы > 128, зарезервированный для программы, прерванной сигналом:Другие значения не создают проблем, поскольку их можно отличить от специальных
$?
значений оболочки .В частности, значения 1 и 2 не используются для особых условий, а являются просто кодами выхода, используемыми встроенными командами, которые могут действовать одинаково, если они не являются встроенными. Похоже, что указатель на предоставленное вами руководство по написанию сценариев bash не является хорошим руководством, поскольку он просто перечисляет коды, используемые bash, без комментариев, является ли конкретный код особым значением, которого следует избегать для собственных сценариев.
Более новые версии Bourne Shell используют
waitid()
вместо того,waitpid()
чтобы ждать завершения программы, иwaitid()
(введенный в 1989 году для SVr4) использует лучший интерфейс системного вызова (аналогично тому, что UNOS использовал в 1980 году).Поскольку новые версии Bourne Shell кодируют причину выхода в отдельной переменной
${.sh.code}
/${.sh.codename}
чем код выхода, который находится в${.sh.status}
/${.sh.termsig}
, см. Http://schillix.sourceforge.net/man/man1/bosh.1.html , код выхода не перегружен с особыми состояниями и, в результате использования `waitid (), оболочка Bourne теперь поддерживает возврат всех 32 битов кода выхода, а не только младших 8 битов.КСТАТИ: будьте осторожны
exit(256)
с C-программой или сценарием оболочки или не похожи на них, так как это приводит$?
к интерпретации как 0 в классической оболочке.источник
waitid()
ошибки примерно в конце мая. Люди из FreeBSD исправили проблему в течение 20 часов, люди из Linux не заинтересованы в исправлении их ошибки. ... и люди Cygwin говорят, что они совместимы с ошибками Linux ;-)_exit
. Пожалуйста, свяжите отчет об ошибке FreeBSD, на который вы ссылаетесь, возможно, я неправильно понимаю проблему, которую вы описываете.${.sh.}
переменные. Однако верно то, что вы говорите «Bourne», а не «Bourne-output» (хотя вы включаете ksh93)./bin/sh
можете полагаться на постоянное поведение этих кросс-платформенных кодов выхода, что не соответствует действительности. (Мне все равно ,/bin/sh
можно ли назвать какую-либо конкретную систему «настоящей оболочкой Борна». Гораздо важнее знать, что ничего этого нет в POSIX, и что большинство вещей, которые вы цитируете как «настоящие системы Unix», не в/bin/sh
любом случае, не POSIX-совместимый .)Для сценариев оболочки я иногда добавляю эквивалент
sysexist.h
оболочки с зарезервированными для оболочки кодами выхода (с префиксомS_EX_
), которые я назвалexit.sh
Это в основном:
И может быть сгенерировано с помощью:
Я не очень часто его использую, но я использую функцию оболочки, которая инвертирует коды ошибок в их строковые форматы. Я назвал это
exit2str
. Предполагая, что вы назвали вышеупомянутыйexit.sh
генераторexit.sh.sh
, код дляexit2str
может быть сгенерирован с помощью (exit2str.sh.sh
):Я использую это в
PS1
моей интерактивной оболочке, чтобы после каждой запускаемой команды я мог видеть ее состояние выхода и строковую форму (если она имеет известную строковую форму):Чтобы получить их, вам необходим источник для функции exit2str:
а затем используйте его в своем
~/.bashrc
файле, чтобы сохранить и перевести код завершения в каждой командной строке и отобразить его в своем приглашении (PS1
):Это очень удобно для наблюдения за тем, как некоторые программы следуют соглашениям о коде выхода, а другие - нет, для изучения соглашений о коде выхода или просто для того, чтобы увидеть, что происходит с большей готовностью. Пользуясь им в течение некоторого времени, я могу сказать, что многие системные ориентированные сценарии оболочки следуют соглашениям.
EX_USAGE
Особенно часто встречается, хотя других кодов не так много. Я стараюсь время от времени следовать соглашениям, хотя всегда есть$S_EX_ANY
(1) для ленивых людей (я один).источник
Пока вы документируете свои коды выхода, чтобы вы помнили их через год, когда вам придется вернуться и настроить скрипт, все будет в порядке. Идея «зарезервированных кодов выхода» на самом деле больше не применима, кроме как сказать, что принято использовать
0
в качестве кода успеха и все остальное в качестве кода ошибки.источник
Лучшая ссылка, которую я смог найти, это: http://tldp.org/LDP/abs/html/exitcodes.html
Согласно этому:
1
это общая ловушка для ошибок, и я всегда видел, как она используется для пользовательских ошибок.2
для неправильного использования встроенных модулей оболочки, таких как синтаксическая ошибкаЧтобы ответить на ваш вопрос напрямую, ваш сценарий будет в порядке, используя зарезервированные коды ошибок, он будет функционировать должным образом, при условии, что вы обрабатываете ошибку на основе кода ошибки = 1/2/3.
Тем не менее, это может привести к путанице, если вы встретите кого-то, кто знает и использует зарезервированные коды ошибок, что кажется довольно редким.
Другой доступный вариант - вывести ошибку, если она есть, и затем выйти, если ваш сценарий следует соглашению Linux «нет новостей, это хорошие новости» и ничего не говорит об успехе.
источник
Исходя из ответов, которые я получил (было сложно выбрать один из них), не вредно указывать определенные типы ошибок с помощью кода завершения, который также использует Bash. Bash (или любая другая оболочка Unix) не будет делать ничего особенного (например, запускать обработчики исключений), если пользовательский скрипт завершает работу с одним из этих кодов ошибок.
Кажется, что автор Advanced Bash-Scripting Guide согласен с BSD, пытающимся стандартизировать коды выхода (
sysexits.h
), и просто рекомендует, чтобы, когда пользователи пишут сценарии оболочки, они не указывали коды выхода, которые уже конфликтуют с предопределенными кодами выхода в процессе использования, т. е. они ограничивают свои пользовательские коды выхода 50 доступными кодами состояния в диапазоне 64-113.Я ценю эту идею (и обоснование), но я бы предпочел, чтобы автор был более явным, чтобы игнорировать совет не вредно, за исключением случаев, когда потребитель скрипта проверяет наличие ошибок, таких как приведенный пример 127 (
command not found
).Соответствующие спецификации POSIX
Я исследовал, что POSIX говорит о кодах выхода, и спецификация POSIX, похоже, совпадает с автором Advanced Bash-Scripting Guide. Я процитировал соответствующие спецификации POSIX (выделено мое):
Состояние выхода для команд
exit
утилитыДальнейшая информация
Что бы это ни стоило, я смог проверить все, кроме одного, из списка кодов выхода со специальными значениями . Эта таблица кодов выхода полезна, поскольку она предоставляет более подробную информацию - и примеры того, как генерировать коды ошибок, документированные в справочнике Bash .
Попытка сгенерировать статус выхода 128
Используя Bash версий 3.2.25 и 4.2.46, я пытался выдать
128 Invalid argument to exit
ошибку, но каждый раз получал 255 (состояние выхода вне диапазона). Например, еслиexit 3.14159
выполняется как часть сценария оболочки или в интерактивной дочерней оболочке, оболочка завершается с кодом255
:Для еще большего удовольствия я также попытался запустить простую C-программу, но в этом случае кажется, что
exit(3)
функция просто преобразовала число с плавающей точкой в int (в данном случае 3) перед выходом:источник