Написание надежного, без ошибок сценария bash всегда является сложной задачей. Даже если вы написать идеальный сценарий bash, он все равно может не сработать из-за внешних факторов, таких как некорректный ввод или проблемы с сетью.
В оболочке bash нет никакого механизма поглощения исключений, такого как конструкции try/catch. Некоторые ошибки bash могут быть молча проигнорированы, но могут иметь последствия в дальнейшем.
Проверка статуса завершения команды
Всегда рекомендуется проверять статус завершения команды, так как ненулевой статус выхода обычно указывает на ошибку
1 2 3 | if ! command; then echo "command returned an error" fi |
Другой (более компактный) способ инициировать обработку ошибок на основе статуса выхода - использовать OR:
1 | <command_1> || <command_2> |
С помощью оператора OR, <command_2> выполняется тогда и только тогда, когда <command_1> возвращает ненулевой статус выхода.
В качестве второй команды, можно использовать свою Bash функцию обработки ошибок
1 2 3 4 5 6 7 | error_exit() { echo "Error: $1" exit 1 } bad-command || error_exit "Some error" |
В Bash имеется встроенная переменная $?, которая сообщает вам статус выхода последней выполненной команды.
Когда вызывается функция bash, $? считывает статус выхода последней команды, вызванной внутри функции. Поскольку некоторые ненулевые коды выхода имеют специальные значения, вы можете обрабатывать их выборочно.
1 2 3 4 5 6 7 8 | status=$? case "$status" in "1") echo "General error";; "2") echo "Misuse of shell builtins";; "126") echo "Command invoked cannot execute";; "128") echo "Invalid argument";; esac |
Выход из сценария при ошибке в Bash
Когда возникает ошибка в сценарии bash, по умолчанию он выводит сообщение об ошибке в stderr, но продолжает выполнение в остальной части сценария. Даже если ввести неправильную команду, это не приведет к завершению работы сценария. Вы просто увидите ошибку "command not found".
Такое поведение оболочки по умолчанию может быть нежелательным для некоторых bash сценариев. Например, если скрипт содержит критический блок кода, в котором не допускаются ошибки, вы хотите, чтобы ваш скрипт немедленно завершал работу при возникновении любой ошибки внутри этого блока . Чтобы активировать это поведение "выход при ошибке" в bash, вы можете использовать команду set следующим образом.
1 2 3 | set -e # некоторый критический блок кода, где ошибка недопустима set +e |
Вызванная с опцией -e, команда set заставляет оболочку bash немедленно завершить работу, если любая последующая команда завершается с ненулевым статусом (вызванным состоянием ошибки). Опция +e возвращает оболочку в режим по умолчанию. set -e эквивалентна set -o errexit. Аналогично, set +e является сокращением команды set +o errexit.
1 2 3 | set -e true | false | true echo "Это будет напечатано" # "false" внутри конвейера не обнаружено |
Если необходимо, чтобы при любом сбое в работе конвейеров также завершался сценарий bash, необходимо добавить опцию -o pipefail.
1 2 3 | set -o pipefail -e true | false | true # "false" внутри конвейера определен правильно echo "Это не будет напечатано" |
Для "защиты" критический блока в сценарии от любого типов ошибок команд или ошибок конвейера, необходимо использовать следующую комбинацию команд set.
1 2 3 | set -o pipefail -e # некоторый критический блок кода, в котором не допускается ошибка или ошибка конвейера set +o pipefail +e |