Сценарии оболочки: умереть при любой ошибке

Предположим, что скрипт оболочки (/ bin / sh или / bin / bash) содержит несколько команд. Как я могу сделать так, чтобы скрипт завершал работу, если какая-либо из команд имеет сбойный статус завершения? Очевидно, что можно использовать блоки и / или обратные вызовы, но есть ли более чистый, более краткий способ? Использование && на самом деле тоже не вариант, потому что команды могут быть длинными или скрипт может иметь нетривиальные вещи, такие как циклы и условные выражения.

15.12.2008 15:41:49
3 ОТВЕТА
РЕШЕНИЕ

Со стандартным shи bashвы можете

set -e

Это будет

$ help set
...
        -e  Exit immediately if a command exits with a non-zero status.

Это также работает (из того, что я мог собрать) с zsh. Это также должно работать для любого потомка оболочки Bourne.

С помощью csh/ tcsh, вы должны запустить свой скрипт с#!/bin/csh -e

63
16.12.2008 03:59:14
Спасибо, похоже, это то, что я хочу. Я должен оттачивать свой Google фу, я думаю ... :)
Pistos 15.12.2008 15:56:19
Обратите внимание, что команды в условных выражениях могут давать сбой, не вызывая сценарий для выхода, что крайне важно. Например: если что-то grep / some / where; затем: это было найдено; еще: это не было найдено; Фай отлично работает, независимо от того, что-то найдено в / некоторые / где.
Jonathan Leffler 16.12.2008 04:00:48
Вы говорите "стандартная ш". Значит ли это, что это POSIX? Изменить: я посмотрел его, и это POSIX: pubs.opengroup.org/onlinepubs/009695399/utilities/set.html
Taywee 28.12.2015 21:36:04

Может быть, вы могли бы использовать:

$ <any_command> || exit 1
20
3.08.2009 14:06:42
Этот шаблон полезен для выборочного выхода при сбое отдельных команд, а также, если вы хотите сначала распечатать пользовательское сообщение об ошибке . Чтобы сделать последнее, используйте что-то вроде <any_command> || eval 'echo "Please ensure ..." 1>&2; exit 1'ПРИМЕЧАНИЕ: evalхитрость необходима для группировки команд echoи exitкоманд без создания под- оболочки; использование вложенной оболочки (как было бы, если бы вы использовали круглые скобки) сделало бы exitнеэффективным.
mklement0 24.05.2012 03:19:43
Живи и учись: Bash имеет функцию группирования команд, поэтому нет необходимости в evalупомянутом трюке. Вместо этого используйте <any_command> || { echo "Please ensure ..." 1>&2; exit; }(запишите необходимое ;перед закрытием }).
mklement0 7.06.2012 02:30:21

Вы можете проверить $? чтобы увидеть, какой самый последний код выхода ..

например

#!/bin/sh
# A Tidier approach

check_errs()
{
  # Function. Parameter 1 is the return code
  # Para. 2 is text to display on failure.
  if [ "${1}" -ne "0" ]; then
    echo "ERROR # ${1} : ${2}"
    # as a bonus, make our script exit with the right error code.
    exit ${1}
  fi
}

### main script starts here ###

grep "^${1}:" /etc/passwd > /dev/null 2>&1
check_errs $? "User ${1} not found in /etc/passwd"
USERNAME=`grep "^${1}:" /etc/passwd|cut -d":" -f1`
check_errs $? "Cut returned an error"
echo "USERNAME: $USERNAME"
check_errs $? "echo returned an error - very strange!"
0
7.02.2012 22:12:10
-1: это слишком частый антипаттерн. Решение @ Barun проще и понятнее.
tripleee 8.02.2012 04:34:22
тот же сценарий, что и выше, но в качестве более аккуратного «более аккуратного подхода» (все в одной строке): foo = $ (grep "^ $ {1}" / etc / passwd) && foo = $ (echo "$ foo" | cut - d: -f1) && echo ok || echo not_ok (nb: если используется bash и не ограничивается sh, можно получить состояние выхода любой части конвейера, что упрощает логику grep / cut.)
michael 9.06.2012 10:36:59
+1: это позволяет правильно обрабатывать ошибки в сценарии без усложнения подоболочек.
symcbean 8.09.2016 15:38:49