Автоматический выход из скрипта оболочки bash при ошибке

406

Я писал некоторую оболочку script, и я бы счел ее полезной, если бы была возможность остановить выполнение указанной оболочки script, если какая-либо из команд не удалась. Ниже приведен пример:

#!/bin/bash  

cd some_dir  

./configure --some-flags  

make  

make install

Таким образом, в этом случае, если script не может измениться в указанную директорию, тогда он, конечно, не захочет делать. /configure после этого.

Теперь я хорошо знаю, что у меня могла бы быть проверка if для каждой команды (которая, по моему мнению, является безнадежным решением), но существует ли глобальная настройка для выхода script, если одна из команд выходит из строя?

  • 2
    Ответ идет к Адаму за подробностями относительно set -e (что именно нужно). Также спасибо a_m0d за информацию о ловушках (хотя и не актуально на 100%).
  • 0
    Относятся ли эти ответы к sh так же, как к bash ?
Теги:
exit

7 ответов

610
Лучший ответ

Используйте set -e builtin:

#!/bin/bash
set -e
# Any subsequent(*) commands which fail will cause the shell script to exit immediately

В качестве альтернативы вы можете передать -e в командной строке:

bash -e my_script.sh

Вы также можете отключить это поведение с помощью set +e.

(*) Примечание:

Сбой не завершается, если команда, которая не работает, является частью список команд сразу после ключевого слова в то время как или дочасть теста после if или elif зарезервированных слов, часть любой команды, выполненной в списке && или ||, за исключением команды после окончательной & или ||, любая команда в конвейере, но последнее, или если возвращаемое значение команды инвертируется с

(от man bash)

  • 5
    Это тоже встроенная оболочка Bourne?
  • 4
    @ Да. См. Pubs.opengroup.org/onlinepubs/009695399/utilities/…
Показать ещё 10 комментариев
53

Чтобы выйти из script, как только одна из команд не удалась, добавьте это в начале:

set -e

Это приводит к тому, что script выходит немедленно, когда некоторая команда, которая не является частью какого-либо теста (например, в if [ ... ] или конструкторе &&), выходит с ненулевым кодом выхода.

35

Вот как это сделать:

#!/bin/sh

abort()
{
    echo >&2 '
***************
*** ABORTED ***
***************
'
    echo "An error occurred. Exiting..." >&2
    exit 1
}

trap 'abort' 0

set -e

# Add your script below....
# If an error occurs, the abort() function will be called.
#----------------------------------------------------------
# ===> Your script goes here
# Done!
trap : 0

echo >&2 '
************
*** DONE *** 
************
'
  • 2
    trap 'abort' 0 <- почему вы делаете trap на «0», а не «1»?
  • 2
    0 - EXIT , ловушка IOW при выходе
Показать ещё 2 комментария
15

Я думаю, что вы ищете команду trap:

trap command signal [signal ...]

Для получения дополнительной информации см. эту страницу.

Другим вариантом является использование команды set -e в верхней части вашего script - это приведет к завершению script, если какая-либо программа/команда вернет неверное значение.

15

Одна идиома:

cd some_dir && ./configure --some-flags && make && make install

Я понимаю, что это может затянуться, но для больших скриптов вы можете разбить его на логические функции.

  • 8
    и вы можете добавить новую строку после && для удобства чтения
14

В случае, если script вызывает индекс внутри, опция pipefail может быть полезна.

set -e
set -o pipefail

-e (errexit): Abort script при первой ошибке, когда команда выходит с ненулевым статусом (за исключением циклов while или while, if-tests, list)

-o pipefail: Заставляет конвейер возвращать статус завершения последней команды в канале, который возвратил ненулевое возвращаемое значение.

Глава 33. Параметры

  • 3
    Это "set -o errexit" или "set -e".
14

Альтернатива принятому ответу, который подходит в первой строке:

#!/bin/bash -e

cd some_dir  

./configure --some-flags  

make  

make install
  • 9
    Я видел это раньше (помещая '-e' в строке #!), Но для меня это не работает так, как ожидалось с bash v3.2.57 на Mac OS X. Далее следуют простые тестовые сценарии, которые вызывают / usr / bin / false эхом не спасать, когда ожидается. Использование "set -e", как принято выше, работает нормально.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню