Почему 0 истинно, а ложно 1 в оболочке? - PullRequest
100 голосов
/ 29 мая 2010
false; echo $?

Выше будет выводиться 1, что противоречит всем другим языкам программирования, которые я знаю.

Есть ли причина в этом?

Ответы [ 10 ]

81 голосов
/ 29 мая 2010

Это соглашение, но особенно полезное, когда вы думаете об этом. В общем, если программа успешна, это все, что вам нужно знать. Однако в случае сбоя вам может потребоваться информация всех видов о сбое - почему это произошло, как его исправить и т. Д. Имея нулевое значение «успех» и ненулевое среднее значение отказа, вы можете довольно легко проверить успешность и исследуйте конкретную ошибку для получения более подробной информации, если хотите. Многие API и фреймворки имеют похожее соглашение - функции, которые успешно работают, возвращают 0, а те, которые не работают, возвращают код ошибки, описывающий конкретный случай сбоя.

65 голосов
/ 29 мая 2010

Bash - это язык программирования (сценариев), но это также оболочка и пользовательский интерфейс. Если 0 было ошибкой, то программа могла выдавать только один тип ошибки.

Однако в Bash любое ненулевое значение является ошибкой, и мы можем использовать любое число от 1-255 для представления ошибки. Это означает, что мы можем иметь много разных видов ошибок. 1 является общей ошибкой, 126 означает, что файл не может быть выполнен, 127 означает «команда не найдена» и т. Д. Вот список Bash Коды выхода со специальными значениями , показывающие некоторые из наиболее распространенные коды выхода.

Есть также много видов успеха (статус выхода 0). Тем не менее, успех позволит вам перейти к следующему шагу - вы можете напечатать результаты на экране или выполнить команду и т. Д.

24 голосов
/ 29 января 2014

Здесь есть две связанные проблемы.

Во-первых, вопрос OP, Почему 0 имеет значение true, а false - это 1 в оболочке? , а второй, , почему приложения возвращают 0 для успеха и ненулевое значение для сбоя?

Чтобы ответить на вопрос ОП, нам нужно понять второй вопрос. Многочисленные ответы на этот пост описывают, что это соглашение, и перечисляют некоторые тонкости, которые дает это соглашение. Некоторые из этих тонкостей кратко изложены ниже.

Почему приложения возвращают 0 для успеха и ненулевое значение для отказа?

Код, который вызывает операцию, должен знать две вещи о состоянии завершения операции. Операция завершилась успешно? [* 1] И если операция не завершается успешно Почему операция завершилась неудачно? Для обозначения успеха можно использовать любое значение. Но 0 удобнее, чем любое другое число, потому что оно переносимо между платформами. Обобщая ответ xibo на этот вопрос 16 августа 2011 года:

Ноль не зависит от кодировки.

Если мы хотим сохранить один (1) в 32-разрядном целочисленном слове, первым вопросом будет «слово с прямым порядком байтов или слово с прямым порядком байтов?», А затем «как долго байты составляют мало- endian word? ", а ноль всегда будет выглядеть одинаково.

Также следует ожидать, что некоторые люди в какой-то момент произносят ошибку на чар, шорт или даже на плавание. (int) ((char) ENOLCK) не является ENOLCK, если длина char не меньше 8 бит (7-битные ASCII-машины с символами поддерживаются UNIX), тогда как (int) ((char) 0) равен 0 независимо от архитектурные детали чар.

Как только будет определено, что 0 будет возвращаемым значением для успеха, тогда имеет смысл использовать любое ненулевое значение для отказа. Это позволяет многим кодам выхода ответить на вопрос, почему операция не удалась.

Почему 0 истинно, а ложно 1 в оболочке?

Одним из основных способов использования оболочек является автоматизация процессов с помощью сценариев. Обычно это означает, что вы вызываете операцию, а затем делаете что-то еще в зависимости от состояния выхода операции. Филипп А. хорошо объяснил в своем ответе на этот пост, что

В оболочках bash и unix в целом возвращаемые значения не являются логическими. Это целочисленные коды выхода.

Затем необходимо интерпретировать состояние завершения этих операций как логическое значение. Имеет смысл сопоставить успешный (0) статус выхода с истинным значением, а любой ненулевой статус / статус отказа - с ложным. Это позволяет условно выполнять связанные команды оболочки.

Вот пример mkdir deleteme && cd $_ && pwd. Поскольку оболочка интерпретирует 0 как true, эта команда удобно работает, как и ожидалось. Если бы оболочка интерпретировала 0 как ложное, вам пришлось бы инвертировать интерпретированный статус выхода для каждой операции.

Короче говоря, для оболочки было бы бессмысленно интерпретировать 0 как ложное, учитывая соглашение, что приложения возвращают 0 для успешного завершения состояния.


[* 1]: Да, во многих случаях операции должны возвращать не просто простое сообщение об успехе, но это выходит за рамки этого потока.

См. Также Приложение E в Расширенном руководстве по написанию сценариев Bash

15 голосов
/ 03 ноября 2011

Один фундаментальный момент, который я считаю важным понять, заключается в следующем. В оболочках bash и unix вообще возвращаемые значения не являются логическими. Это целочисленные коды выхода. Таким образом, вы должны оценивать их в соответствии с соглашением, говоря, что 0 означает успех, а другие значения означают некоторую ошибку.

С операторами test, [ ] или [[ ]] условия bash оцениваются как true в случае кода выхода 0 (результат / bin / true). В противном случае они оцениваются как ложные.

Строки оцениваются иначе, чем коды выхода:

if [ 0 ] ; then echo not null ; fi
if [ $(echo 0) ] ; then echo not null ; fi

if [ -z "" ] ; then echo null ; fi

Арифметический оператор (( )) интерпретирует 1 и 0 как true и false. Но этот оператор не может использоваться в качестве полной замены для test, [ ] или [[ ]]. Вот пример, показывающий, когда арифметический оператор полезен:

for (( counter = 0 ; counter < 10 ; counter ++ )) ; do
  if (( counter % 2 )) ; then echo "odd number $counter" ; fi
done
15 голосов
/ 29 мая 2010

Это просто соглашение, что код выхода 0 означает успех. EXIT_SUCCESS будет 0 почти во всех современных системах.

EDIT:

"почему и тест 0, и тест 1 возвращают 0 (успех)?"

Это совершенно другой вопрос. Ответ заключается в том, что передача одного аргумента для проверки всегда приводит к успеху, если этот аргумент не является пустой строкой (""). См. Документацию Open Group .

.
12 голосов
/ 29 мая 2010

Обычно программы возвращают ноль для успеха, ненулевое значение для сбоя; false возвращает 1, потому что это удобное ненулевое значение, но обычно любое ненулевое значение означает какой-либо сбой, и многие программы возвращают разные ненулевые значения, чтобы указать разные режимы сбоя

4 голосов
/ 31 мая 2010

AFAIK это происходит из соглашения C, что вы должны вернуть 0 в случае успеха. См:

man close

Большая часть API C (POSIX) построена следующим образом. http://en.wikipedia.org/wiki/C_POSIX_library

3 голосов
/ 14 апреля 2016

это соглашение, восходящее к ранним дням Unix.

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

Оболочки следуют этому соглашению, 0 означает, что последняя команда выполнена успешно, в противном случае - ненулевое значение. Аналогично, ненулевое возвращаемое значение удобно для выходных сообщений об ошибках: например, 1: «мертвый мозг», 2: «бессердечный» и т. Д.

3 голосов
/ 14 февраля 2014

Вы пытаетесь приравнять истину / ложь к успеху / неудаче.

Это два полностью, хотя поначалу тонко различающихся дихотомии!

В сценариях оболочки нет такого понятия, как true / false. «Выражения» оболочки не интерпретируются как истина / ложь. Скорее, «выражения» оболочки - это процессы, которые либо завершаются успешно, либо завершаются неудачей.

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

В C мы создаем программу. В сценарии оболочки мы запускаем несколько программ, чтобы что-то сделать.

разница!

1 голос
/ 13 декабря 2018

Может быть, хороший способ запомнить это:

  • Коды возврата ответа "каков ответ?"true (или другой результат) или false
  • Коды выхода отвечают "в чем проблема?"код выхода или нет проблем (0)
...