6

Прерывание скрипта оболочки при возвращении любой команды ненулевого значения

8

У меня есть Bash-скрипт, который выполняет несколько команд. Я хотел бы, чтобы скрипт автоматически завершался с кодом возврата 1, если любая из команд возвращает ненулевое значение.

Есть ли способ сделать это без явной проверки результата каждой команды?

Например, вместо следующего кода:

dosomething1
if [[ $? -ne 0 ]]; then
    exit 1
fi

dosomething2
if [[ $? -ne 0 ]]; then
    exit 1
fi

Я хотел бы узнать, можно ли упростить этот процесс.

5 ответ(ов)

1

Условные операторы if в вашем примере не нужны. Просто сделайте это так:

dosomething1 || exit 1

Если вы последуете совету Ville Laurikari и используете set -e, то для некоторых команд вам может понадобиться использовать следующую конструкцию:

dosomething || true

Использование || true позволит команде вернуть значение true, даже если сама команда завершится с ошибкой, благодаря чему опция -e не приведет к остановке скрипта.

0

Если вам нужно выполнить очистку при выходе из скрипта, вы можете использовать команду trap с псевдосигналом ERR. Это работает так же, как и ловля других сигналов, таких как INT; в bash генерируется сигнал ERR, если любая команда заканчивается с ненулевым кодом возврата:

# Устанавливаем ловушку с   
#    trap COMMAND SIGNAME [SIGNAME2 SIGNAME3...]
trap "rm -f /tmp/$MYTMPFILE; exit 1" ERR INT TERM
command1
command2
command3
# Частично отключаем ловушку.
trap - ERR
# Теперь прерывание с помощью Ctrl+C все еще вызовет очистку,
# но ненужный ненулевой код возврата не вызовет:
ps aux | grep blahblahblah

Кроме того, особенно если вы используете set -e, вы можете установить ловушку на сигнал EXIT; ваша ловушка будет выполнена при любом выходе из скрипта, включая нормальное завершение, прерывания или выход, вызванный опцией -e и т.д.

0

Переменная $? редко требуется. Псевдо-идиома command; if [ $? -eq 0 ]; then X; fi всегда должна быть записана в виде if command; then X; fi.

Случаи, когда $? необходимо использовать, возникают, если нужно проверить его на соответствие нескольким значениям:

command
case $? in
  (0) X;;
  (1) Y;;
  (2) Z;;
esac

Или когда $? нужно переиспользовать или каким-либо образом обработать:

if command; then
  echo "command successful" >&2
else
  ret=$?
  echo "command failed with exit code $ret" >&2
  exit $ret
fi
0

Запустите его с параметром -e или добавьте set -e в начало скрипта.

Также обратите внимание на set -u.

0

Этот скрипт обрабатывает ошибки так, что при возникновении проблемы он выводит сообщение об ошибке красным цветом и завершает выполнение.

Добавьте следующий код в начало вашего bash-скрипта:

# Обработка ошибок в BASH:
#   завершить выполнение при неудачном выполнении команды
set -e
#   отслеживать последнюю выполненную команду
trap 'LAST_COMMAND=$CURRENT_COMMAND; CURRENT_COMMAND=$BASH_COMMAND' DEBUG
#   при ошибке: вывести неудавшуюся команду
trap 'ERROR_CODE=$?; FAILED_COMMAND=$LAST_COMMAND; tput setaf 1; echo "ERROR: команда \"$FAILED_COMMAND\" завершилась с кодом $ERROR_CODE"; tput sgr0;' ERR INT TERM

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

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь