Ненулевой статус выхода для чистого выхода

15

Допустимо ли возвращать ненулевой код завершения, если рассматриваемая программа работала правильно? Например, скажем, у меня есть простая программа, которая (только) выполняет следующее:

Программа принимает N аргументов. Возвращает код выхода min (N, 255). Обратите внимание, что любой N действителен для программы.

Более реалистичная программа может возвращать разные коды для успешно запущенных программ, которые обозначают разные вещи. Должны ли эти программы вместо этого записывать эту информацию в поток, например в stdout?

Томас Эдинг
источник

Ответы:

24

Это зависит от окружающей среды, но я бы сказал, что это плохой стиль.

В Unix-подобных системах существует строгое соглашение, что состояние выхода 0 означает успех, а любое ненулевое состояние выхода означает сбой. Некоторые, но не все, программы различают различные виды сбоев с разными ненулевыми кодами выхода; например, grepобычно возвращает 0, если шаблон был найден, 1, если его не было, и 2 (или более), если произошла ошибка, например, отсутствующий файл.

Это соглашение в значительной степени встроено в оболочку Unix. Например, в sh, bashи других подобных Борну оболочках, ifоператор обрабатывает состояние выхода 0 как успех / истина, а ненулевой статус выхода - сбой / ложь:

if your-command
then
    echo ok
else
    echo FAILURE
fi

Я считаю, что соглашения под MS Windows похожи.

Теперь, конечно, ничто не мешает вам написать свою собственную программу, использующую нетрадиционные коды выхода, особенно если с ней больше ничего не будет взаимодействовать, но имейте в виду, что вы нарушаете хорошо установленное соглашение, и оно может вернуться и укусить вас позже ,

Обычный способ для программы вернуть такую ​​информацию - распечатать ее по адресу stdout:

status = $(your-command)
echo Result is $status
Кит Томпсон
источник
7
+1 для объяснения соглашения, этот подход сломал бы большинство моих сценариев оболочки, если бы я положил set -eкуда-нибудь.
Бенджамин Банье
Аналогично grep, diffвозвращает 1 при обнаружении различий; и> 1, если произошла ошибка.
7heo.tk
6

Зависит от того, что ожидает ваша среда.

Мой любимый по странности, из Википедии :

В OpenVMS успех обозначается нечетными значениями, а сбой - четными. Значение представляет собой 32-разрядное целое число с подполями: контрольные биты, номер объекта, номер сообщения и серьезность. Значения серьезности делятся между успехом (успех, информация) и неудачей (предупреждение, ошибка, фатальный).

Билл
источник
4

Я думаю, что есть прецедент, если код завершения возвращает значащую, релевантную информацию вызывающей стороне, и определение успеха на самом деле не является двоичным. Прецедент, о котором я думаю, - это робокопия, которая возвращает множество разных вещей в зависимости от того, что произошло .

Я добавлю, что у нас всегда возникает какая-то отладка из-за этого - большинство утилит предполагают, что код выхода 0 == success, поэтому волнуюсь, когда robocopy возвращает 1, потому что он скопировал материал не ноль, потому что он не копировал, но не копировал Также нет ошибки.

Уайетт Барнетт
источник
2

не возвращать 0 для успешного запуска - плохая идея, потому что это может вызвать путаницу у тех, кто работает с вашей программой. Что если кто-то запустил вашу программу более 100 раз с разными входными данными и захотел узнать, сколько из них завершилось неудачно или завершено успешно, наличие единственного значения успеха значительно упрощает поиск различий, чем наличие множества различных значений.

Если у вас есть программа с несколькими успешными путями возврата, которые могут обозначать разные вещи, я бы сказал, что это признак того, что ваша программа плохо спроектирована.

Ryathal
источник
2

Я знаю случай, который я считаю приемлемым. Мне известна структура тестирования, которая завершается с общим количеством неудачных тестов. Так, например, если тестовый исполнитель завершается без неудачных тестов, он завершается с нулем. Если один тест не пройден, даже если сам тестовый исполнитель выполнялся с перебоями, он завершается с одним 1. Если два не пройдены, он возвращает 2 и т. Д. Это до 250, что означает «250 или более неудачных тестов».

Он использует коды выхода> 250 для обозначения аварийных выходов.

Хотя это нарушает соглашение, на практике это хорошо работает.

Брайан Оукли
источник
3
Я не думаю , что это делает нарушение конвенции - тестирование прошло успешно , если нет ошибок; любой ненулевой код результата указывает на неудачные тесты.
Беван
1
Это «выход из состояния ошибки, указывающий на более чем 0 ошибок», и хотя он может нарушать точную общую семантику состояния выхода, он, конечно, не нарушает более крупное соглашение «0 в порядке, все, что больше 0, является ошибкой» ,
Ватин
2

Это действительно зависит от того, что вы пытаетесь передать с помощью кода. Например, DB2 возвращает 100, если данные не найдены, различные другие положительные значения для предупреждений и отрицательные значения для ошибок. Oracle делает нечто подобное.

Поэтому, если существуют разные состояния успеха, возможно, стоит использовать различные возвращаемые значения.

Мэтью Флинн
источник
2

Хороший пример: man sa-update (spamassassin)

КОДЫ ВЫХОДА

  • Код выхода 0 означает, что обновление было доступно, было успешно загружено и установлено, если --checkonly не было указано.
  • Код выхода 1 означает, что свежих обновлений не было.
  • Код выхода 2 означает ...

В этом случае выход 1 является просто информативным кодом. Однако, если бы я написал код, я бы не выбрал 1, так как обычно это сбой в сети.

выворачивать наизнанку
источник