Зачем нужно выходить из скрипта Bash?
Допустим, вы пишете сценарий… есть одна вещь, которая почти наверняка…
В какой-то момент ваш сценарий, скорее всего, даст сбой из-за непредвиденных обстоятельств, которые вы, возможно, не учли.
Итак, что можно с этим сделать?
Как выйти из скрипта Bash в случае возникновения ошибок?
Bash предоставляет команду выхода из скрипта в случае возникновения ошибок, команду выхода. Аргумент N (статус выхода) может быть передан команде выхода, чтобы указать, был ли скрипт выполнен успешно (N = 0) или неудачно (N!= 0). Если N опущено, команда выхода принимает статус выхода последней выполненной команды.
В этом руководстве вы узнаете, как использовать команду выхода в своих скриптах, чтобы сделать их более надежными и обеспечить удобство использования ваших скриптов.
Давайте начнем.
Завершить Bash-скрипт с ошибкой
Что можно сделать, чтобы писать надежные скрипты, которые не будут давать сбой неожиданным образом в случае ошибок?
Ответ на этот вопрос: не забывайте об обработке ошибок.
Вместо того чтобы «надеяться», что с вашей программой все будет в порядке, вы можете предсказать возможные сбои и решить, как ваша программа будет на них реагировать.
Как вы будете справляться с ошибками, если они возникнут? Что увидит пользователь?
Мы рассмотрим, как работает обработка ошибок в скриптах Bash (или скриптах Shell в целом).
Эти концепции применимы ко всем языкам программирования, даже если способы обработки ошибок в них реализованы по-разному.
Для обработки ошибок в Bash мы будем использовать команду exit, синтаксис которой следующий:
exit N
Где N — код выхода Bash (или статус выхода), используемый для выхода из скрипта во время его выполнения.
Различные значения N указывают на успешное или неудачное завершение скрипта.
Но почему разные коды завершения зависят от успеха или неудачи сценария?
Потому что часто другие программы будут вызывать ваш скрипт, и им нужно будет понять, все ли идет нормально с выполнением вашего скрипта или нет, в рамках обработки ошибок.
Давайте посмотрим, что означает выход 1.
Что такое Exit 0 и Exit 1 в скрипте Bash?
Как выйти из скрипта Bash в случае ошибки?
Стандартное соглашение следующее:
Код выхода Bash | Значение |
Ноль (0) | Успех |
Ненулевое (1, 2, 3 и т. д.) | Отказ |
Как видно из таблицы выше, сбои могут быть представлены любыми ненулевыми кодами выхода.
Например:
- 1 может использоваться, если скрипту переданы неверные аргументы
- 2 если скрипт не может найти нужный ему файл
- 3 если нужный файл имеет неправильный формат
- И так далее…
Вы можете проявить творческий подход и использовать ненулевые коды выхода Bash, чтобы четко определить причину сбоя вашего скрипта.
Итак, возвращаемся к команде выхода.
Что произойдёт, когда он будет выполнен?
Команда выхода возвращает код выхода обратно в оболочку.
Вот пример…
Давайте напишем скрипт под названием exit_status.sh:
#!/bin/bash
echo "Exit command test"
exit 0
Итак, здесь мы передаем код выхода 0 команде выхода.
Как мы можем проверить, что это действительно тот код, который скрипт передал обратно в оболочку?
Мы используем переменную $?. Запомните это, это очень важно!
$? — переменная, содержащая код завершения последней выполненной команды.
И как мы можем определить его значение?
Используя команду echo, мы таким же образом выводим значение любой переменной:
(localhost)$./exit_status.sh
Exit command test
(localhost)$ echo $?
0
Вуаля, вот код выхода 0.
А что произойдет, если мы уберем «выход 0» из скрипта?
#!/bin/bash
echo "Exit command test"
Запустите скрипт еще раз и проверьте значение $?:
(localhost)$./exit_status.sh
Exit command test
(localhost)$ echo $?
0
Мы все равно получаем код выхода 0…
Итак, ничего не изменилось… почему?
Потому что каждая выполняемая нами команда, включая команду echo (единственная команда в нашем скрипте), возвращает код выхода.
В этом случае команда echo, выполненная как часть скрипта, возвращает код завершения 0, поскольку команда echo «Exit command test» выполнена успешно.
Подробнее о статусе команды Bash Exit
Я покажу вам пример того, как код выхода применяется к выполнению любых команд.
Это действительно важно для вашего знания Bash, и я хочу убедиться, что вам это понятно.
Вот пример с командой cat (это применимо ко всем командам)…
Я открываю оболочку на своем компьютере и в текущем каталоге у меня есть следующие файлы:
(localhost)$ ls -al
total 16
drwxr-xr-x 4 myuser mygroup 128 4 Jul 12:38.
drwxr-xr-x 11 myuser mygroup 352 4 Jul 12:38..
-rw-r--r-- 1 myuser mygroup 10 4 Jul 12:38 test_file1
-rw-r--r-- 1 myuser mygroup 10 4 Jul 12:38 test_file2
Если я использую команду cat для просмотра содержимого файла test_file1, то код выхода, сохраненный в переменной $? после выполнения команды cat, равен 0, поскольку выполнение команды cat прошло успешно:
(localhost)$ cat test_file1
Test file
(localhost)$ echo $?
0
Если по ошибке я попытаюсь распечатать содержимое файла test_file3 (который не существует), значение переменной $? не будет равно 0.
В этом случае это 1, но он может иметь и другие значения, отличные от нуля. Это полезно для представления нескольких типов ошибок для данной команды:
(localhost)$ cat test_file3
cat: test_file3: No such file or directory
(localhost)$ echo $?
1
Все ясно?
Если у вас есть какие-либо вопросы, пожалуйста, дайте мне знать в комментариях ниже.
Пример провала сценария
Теперь давайте изменим команду echo в простом скрипте, который мы использовали ранее.
Мы хотим запустить его с неправильным синтаксисом и посмотреть, завершится ли он с ненулевым кодом выхода.
Удалите двойные кавычки в конце команды echo, как показано ниже:
#!/bin/bash
echo "Exit command test
Если мы выполним скрипт, то увидим сообщение «syntax error: unexpected end of file»:
(localhost)$./exit_status.sh
./exit_status.sh: line 3: unexpected EOF while looking for matching `"'
./exit_status.sh: line 4: syntax error: unexpected end of file
(localhost)$ echo $?
2
А код выхода — 2. То есть, ненулевой код выхода, как мы и ожидали.
Как упоминалось ранее, помните о переменной $?, поскольку она имеет большое значение при обработке ошибок и делает ваши скрипты более надежными.
Оператор Bash if-else также можно использовать для написания более сложной логики, которая проверяет значение переменной $? и выполняет различные действия на его основе.
Bash If Else применен к переменной $?
Давайте посмотрим, как можно использовать оператор Bash if else вместе с переменной $?.
Следующий скрипт пытается создать подкаталог tmp/project в текущем каталоге.
В условии оператора if мы проверяем, отличается ли значение переменной $? от 0. Если это так, мы выводим сообщение об ошибке и завершаем работу скрипта с кодом выхода 1.
Ветвь else выводит сообщение об успешном выполнении и выполняется только в том случае, если значение $? равно 0.
#!/bin/bash
mkdir tmp/project
if [[ $? -ne 0 ]] ; then
echo "Unable to create directory tmp/project"
exit 1
else
echo "Directory tmp/project created successfully"
fi
Давайте запустим скрипт:
(localhost)$./exit.sh
mkdir: tmp: No such file or directory
Unable to create directory tmp/project
(localhost)$ echo $?
1
Команда mkdir завершается ошибкой, поскольку каталог tmp не существует, и, как и ожидалось, статус завершения скрипта равен 1.
Я хочу посмотреть, что произойдет, если я обновлю команду mkdir в скрипте, включив флаг -p, который создает каталог tmp, если он не существует:
mkdir -p tmp/project
Вот результат работы скрипта:
(localhost)$./exit.sh
Directory tmp/project created successfully
(localhost)$ echo $?
0
На этот раз каталог создан успешно, а код выхода, возвращаемый скриптом, равен нулю, как и ожидалось (выполняется ветвь else оператора if else).
Заключение
Мы через многое прошли!
Теперь вы знаете:
- Почему в скриптах Bash используются выходы 0 и 1.
- Как можно использовать переменную $? для чтения кода выхода, возвращаемого командой (или скриптом)
- Способ использования оператора Bash if else вместе с переменной $?.
А теперь ваша очередь…
Какие неудачи вы хотели бы учесть в своем сценарии?