Понимание кодов выхода и их использование в сценариях Bash | by Benjamin Cane
Чтение: 5 мин.·
2 сентября 2014 г. Photo by Alex Holyoakeони будут полезны для инструментов автоматизации и мониторинга. Я заметил одну вещь: иногда скрипты используют коды выхода, а иногда нет. Кажется, что люди легко забывают коды выхода, но они являются невероятно важной частью любого скрипта. Особенно, если этот скрипт используется для командной строки.
В системах Unix и Linux программы могут передавать значение своему родительскому процессу при завершении. Это значение называется кодом выхода или статусом выхода. В системах POSIX стандартное соглашение заключается в том, что программа передает 0
для успешного выполнения и 1
или выше для неудачного выполнения.
Почему это важно? Если вы посмотрите на коды выхода в контексте сценариев, написанных для использования в командной строке, ответ будет очень простым. Любой скрипт, который каким-то образом полезен, неизбежно будет либо использован в другом скрипте, либо обернут одним лайнером bash. Это становится особенно верным, если сценарий используется с инструментами автоматизации, такими как SaltStack, или инструментами мониторинга, такими как Nagios. Эти программы будут выполнять сценарии и проверять код состояния, чтобы определить, был ли этот сценарий успешным или нет.
Помимо этих причин, в ваших скриптах существуют коды выхода, даже если вы их не определяете. Не определяя правильные коды выхода, вы можете ложно сообщать об успешном выполнении, что может вызвать проблемы в зависимости от того, что делает скрипт.
В Linux любой сценарий, запускаемый из командной строки, имеет код выхода. В сценариях Bash, если код выхода не указан в самом сценарии, используемый код выхода будет кодом выхода последней выполненной команды. Чтобы немного лучше объяснить коды выхода, мы собираемся использовать быстрый пример сценария.
Пример сценария:
#!/bin/bash
touch /root/test
echo created file
Приведенный выше пример сценария выполнит как команду touch
, так и команду echo Команда
. Когда мы выполняем этот сценарий (как пользователь без полномочий root), команда touch завершится ошибкой, в идеале, поскольку команда touch не удалась, мы хотели бы, чтобы код выхода сценария указывал на ошибку с соответствующим кодом выхода. Чтобы проверить код выхода, мы можем просто напечатать $?
специальная переменная в bash. Эта переменная будет печатать код выхода последней команды запуска.
Выполнение:
$ ./tmp.sh
касание: невозможно коснуться '/root/test': Отказано в доступе
созданный файл
$ echo $?
0
Как вы можете видеть, после запуска команды ./tmp.sh
код выхода был 0
, что указывает на успех, хотя команда touch не удалась. Пример скрипта запускает две команды touch
и echo
, поскольку мы не указали код выхода, скрипт завершает работу с кодом выхода последней команды запуска. В этом случае последней командой запуска является команда echo
, которая действительно выполнена успешно.
Скрипт:
#!/bin/bash
touch /root/test
Если мы удалим команду echo
из скрипта, мы должны увидеть код выхода touch 9001 2 команда.
Исполнение:
$ ./tmp.sh
touch: не может касаться '/root/test': разрешение отклонено
$ echo $?
1
Как видите, поскольку последней командой была запущена touch
, код выхода отражает истинное состояние скрипта; неуспешный.
При удалении команды echo
из нашего примера скрипта работал, чтобы предоставить код выхода, что происходит, когда мы хотим выполнить одно действие, если touch
было успешным, и другое, если нет. Такие действия, как печать до stdout
в случае успеха и stderr
в случае неудачи.
Ранее мы использовали $?
специальная переменная для печати кода завершения скрипта. Мы также можем использовать эту переменную в нашем скрипте, чтобы проверить, была ли команда touch
успешной или нет.
Сценарий:
#!/bin/bash touch /root/test 2> /dev/nullif [ $? -eq 0 ]
then
echo "Файл успешно создан"
else
echo "Не удалось создать файл" >&2
fi
В приведенной выше версии нашего примера сценария; если код выхода для touch
равен 0
, сценарий выдаст эхо
успешное сообщение. Если код выхода отличается от 0
, это указывает на сбой, и сценарий эхо
выдаст сообщение об ошибке на stderr
.
Выполнение:
$ ./tmp.sh
Не удалось создать файл
Хотя указанная выше версия выдаст сообщение об ошибке, если 9Команда 0011 touch завершается неудачно, она по-прежнему предоставляет код выхода 0
, указывающий на успех.
$ ./tmp.sh
Не удалось создать файл
$ echo $?
0
Поскольку сценарий завершился неудачно, не рекомендуется передавать успешный код выхода любой другой программе, выполняющей этот сценарий. Чтобы добавить наш собственный код выхода в этот сценарий, мы можем просто использовать команду exit
.
Сценарий:
#!/bin/bash коснитесь /root/test 2> /dev/null, если [ $? -eq 0 ]
then
echo "Файл успешно создан"
exit 0
else
echo "Не удалось создать файл" >&2
exit 1
fi
С помощью команды exit
в этом скрипте мы выйдем с успешное сообщение и код выхода 0
, если команда touch
выполнена успешно. Однако, если команда touch
не удалась, мы напечатаем сообщение об ошибке на stderr
и выйдем с кодом 9.0011 1 значение, указывающее на сбой.
Выполнение:
$ ./tmp.sh
Не удалось создать файл
$ echo $?
1
Теперь, когда наш сценарий может сообщать пользователям и программам об успешном или неудачном завершении его работы, мы можем использовать этот сценарий с другими инструментами администрирования или просто использовать его с лайнерами bash one.
Bash One Liner:
$ ./tmp.sh && echo "bam" || (sudo ./tmp.sh && echo "бам" || echo "сбой")
Не удалось создать файл.
Файл успешно создан. Конструкции списка позволяют объединять команды вместе с простыми&&
для и и||
для условий или . Приведенная выше команда выполнит сценарий./tmp.sh
, и если код выхода будет0
, будет выполнена командаecho "bam"
. Если код выхода./tmp.sh
равно1
, однако далее будут выполняться команды в скобках. В скобках команды объединены в цепочку с помощью&&
и||
конструирует снова.Конструкции списка используют коды выхода, чтобы понять, успешно ли выполнена команда. Если сценарии неправильно используют коды выхода, любой пользователь этих сценариев, который использует более сложные команды, такие как конструкции списка, получит неожиданные результаты при сбоях.
Команда
exit
в bash принимает целые числа от0 до 255
, в большинстве случаев0
и1
будет достаточно, однако есть и другие зарезервированные коды выхода, которые можно использовать для более конкретных ошибок. В Linux Documentation Project есть неплохая таблица зарезервированных кодов выхода и того, для чего они используются.Amazon.com: Руководство по устранению неполадок Red Hat Enterprise Linux электронная книга: Cane, Benjamin: Kindle Store
www.amazon.com
Код выхода последней команды Bash
Когда команда bash выполняется, она оставляет после себя код выхода, независимо от успешного или неудачного выполнения. Изучение кода выхода может дать полезную информацию о поведении последней запущенной команды.В этом руководстве вы узнаете, как проверить код выхода последней команды bash и некоторые возможные варианты его использования.
Код выхода Bash
Каждая команда UNIX/Linux, выполняемая сценарием оболочки или пользователем, оставляет статус выхода. Это целое число, которое остается неизменным, пока не будет запущена следующая команда. Если код выхода равен 0, то команда выполнена успешно. Если код выхода не равен нулю (1-255), это означает ошибку.
Код выхода bash можно использовать во многих случаях. Самый очевидный из них — это, конечно же, проверка правильности выполнения последней команды, особенно если команда не генерирует никакого вывода.
В случае bash код выхода предыдущей команды доступен с помощью переменной оболочки «$?».
Проверка кода выхода Bash
Запустите терминал и выполните любую команду.
$ date
Проверить значение переменной оболочки «$?» для кода выхода.
$ эхо $?
Поскольку команда «дата» выполнена успешно, код выхода равен 0. Что произойдет, если возникнет ошибка?
Давайте попробуем запустить несуществующую команду.
$ abcd
Проверьте код выхода.
$ эхо $?
Это ненулевое значение, указывающее, что предыдущая команда не была выполнена должным образом.
Теперь взгляните на следующую команду:
$ cat sample.txt | grep "монета"
При работе с командой, имеющей один или несколько каналов, код выхода будет последним кодом, выполненным в канале. В данном случае это команда grep.
Поскольку команда grep выполнена успешно, будет 0.
$ echo $?
В этом примере, если команда grep завершится ошибкой, код выхода будет ненулевым.
$ cat образец.txt | grep «abcd»
$ эхо $?Включение кода выхода в сценарии
Код выхода также можно использовать для сценариев. Один из простых способов его использования — присвоить его переменной оболочки и работать с ним. Вот пример сценария оболочки, который использует код выхода в качестве условия для вывода определенного вывода.
$ #!/bin/bash
$ echo "привет, мир"
$ status=$?
$ [ $status -eq 0 ] && echo "команда выполнена успешно" || echo "команда не выполнена"При запуске скрипт выдаст следующий вывод.
Теперь давайте посмотрим, что произойдет, если будет запущена недопустимая команда.
$ #!/bin/bash
$ случайная команда
$ статус=$?
$ [ $status -eq 0 ] && echo "команда выполнена успешно" || echo "команда не выполнена"При запуске вывод будет другим.
Значение кода выхода Объяснение
Когда код выхода не равен нулю, значение находится в диапазоне от 1 до 255. Что означает это значение?
Хотя значение ограничено, объяснение каждого значения уникально для программы/сценария. Например, «ls» и «grep» по-разному объясняют код ошибки 1 и 2.
$ man ls
$ man grep
Определение статуса выхода в сценарии
При написании сценария мы можем определить пользовательские значения кода выхода.