Как остановить скрипт bash при неудачном состоянии?

Здесь показано использование || и && в одной строке для конкатенации выполнения команд: Как проверить ошибки apt-get в сценарии bash?

Я пытаясь остановить выполнение скрипта, если какое-то условие терпит неудачу,

, например

false || echo "Obvious error because its false on left" && exit

Здесь он печатает Obvious error because its false on the left и выходит из консоли, что я хотел.

true || echo "This shouldn't print" && exit

Здесь нет эхо-печати, но команда exit работает как ну, т. е. консоль закрыта, не должна ли команда exit не запускаться, потому что команда эхо справа не была выполнена? Или по умолчанию заявление считается ложным в левой части оператора &&?

Редактирование: я должен был упомянуть об этом раньше, моя цель состояла в том, чтобы повторить ошибку и выйти, если бы не было ясно , w.r.t к моему конкретному случаю ошибок уловов при условиях группировки с использованием & amp; & amp; и ||, @ bodhi.zazen ответ решает проблему.

@takatakatek ответ дает более четкое представление об управлении потоком, а ссылки руководства bash превосходны

@muru answer has good объяснение того, почему бы не использовать set -e, если вы хотите, чтобы пользовательские сообщения об ошибках были выбраны с альтернативами использования perl и trap, которые, по моему мнению, являются более надежным способом и я вижу, что я использую его из моего второго скрипта bash!

10
задан 15 June 2017 в 23:57

12 ответов

Вы, вероятно, захотите (как указал steeldriver)

true || { echo "This shouldn't print" && exit; }

В противном случае ваш скрипт читает одно условие в момент времени

a или b, а затем выйдет

Я думаю, что вы хотите или (b и выйти)?

10
ответ дан 22 May 2018 в 21:36
  • 1
    На самом деле, вы должны использовать { ... ; } (как предложил @steeldriver), иначе exit выходит только из подоболочки, а родительская оболочка продолжает выполнение скрипта. – Gordon Davisson 13 June 2017 в 18:00

Вы, вероятно, захотите (как указал steeldriver)

true || { echo "This shouldn't print" && exit; }

В противном случае ваш скрипт читает одно условие в момент времени

a или b, а затем выйдет

Я думаю, что вы хотите или (b и выйти)?

10
ответ дан 18 July 2018 в 11:45

Вы, вероятно, захотите (как указал steeldriver)

true || { echo "This shouldn't print" && exit; }

В противном случае ваш скрипт читает одно условие в момент времени

a или b, а затем выйдет

Я думаю, что вы хотите или (b и выйти)?

10
ответ дан 24 July 2018 в 19:51

Проблема состоит в том, что || и & amp; & amp; только пропустить одну последующую строфу цепочки команд, когда условие не выполняется. Если вы выписываете полную структуру блока, это имеет смысл. То, что вы написали, становится следующим:

if ! true ; then
   echo "This shouldn't print"
else
   exit
fi

Что вы хотите:

if ! true ; then
   echo "This shouldn't print"
   exit
fi

Когда вы используете условные операторы быстрого вызова Bash, лучше не смешивать их. Логику намного легче понять, пока вы ее пишете, и ваши читатели оценят ваш хороший стиль.

http://mywiki.wooledge.org/BashGuide/TestsAndConditionals#Control_Operators http: // mywiki .wooledge.org / BashPitfalls # cmd1_.26.26_cmd2_.7C.7C_cmd3
13
ответ дан 22 May 2018 в 21:36
  • 1
    Да, на мой взгляд, это гораздо больше, чем нужно писать в bash – derHugo 13 June 2017 в 08:32
  • 2
    @takatakatek Это делает более понятным, почему это не удается в моем случае. Я согласен с тем, что логика очевидна в этом, но не является причиной для группировки условий с использованием & amp; & amp; и || заключается в том, чтобы не выражать их, используя условные утверждения? – kosol 15 June 2017 в 23:24
  • 3
    @kosol Да, & amp; & amp; & amp; и || объединить две вещи: проверить статус выхода предыдущей команды и указать одну команду (или группу команд), которая будет выполнена (для & amp; & amp;) или пропущена (для ||). Они могут быть полезны для очень простых случаев, но они не могут заменить полностью выраженные блоки if ... then ... elif ... else ... fi. Я подозреваю, что вы, возможно, не знаете, что Bash не имеет истинных типов boolean , которые видны на более сложных языках. Если статус выхода команды равен 0 (ноль), Bash рассматривает это как true / success . Если статус выхода не равен нулю, Bash рассматривает это как false / failure . – takatakatek 16 June 2017 в 01:34

Самый простой способ сбой при ошибке - использовать опцию -e bash set -e или /bin/bash -e в shebang). Однако это не упрощает отправку пользовательских сообщений об ошибках. Есть несколько идиом, которые могли бы сделать это проще:

die à la Perl

Perl имеет очень удобную команду die, которая печатает сообщение в stderr и создает исключение, которое обычно приводит к завершению сценария. Вы можете эмулировать это:

die () {
  ret=$?
  print "%s\n" "$@" >&2
  exit "$ret"
}

false || die "Obvious error because its false on left"
true || die "This shouldn't print"

trap ERR

Команда trap <command> может использоваться для запуска команды при получении сигнала или при выходе из script (trap ... EXIT), или когда команда возвращает ошибку (trap ... ERR). Итак, что-то вроде:

trap 'ret=$?; printf "%s\n" "$ERR_MSG" >&2; exit "$ret"' ERR

Тогда:

ERR_MSG="Obvious error because its false here"
false
ERR_MSG="This shouldn't print"
true

В любом случае я бы предложил использовать как минимум exit 1, чтобы указать что сценарий завершился неудачно. Обычная exit будет использовать статус выхода предыдущей команды, которая в этих случаях будет командами echo или printf, которые обычно выполняются. Сохранение статуса выхода команды сбоя, как я сделал здесь, было бы неплохо.

7
ответ дан 22 May 2018 в 21:36

Вы можете попробовать немного поэкспериментировать с запуском скрипта с помощью

#!/bin/bash -e

. -e гарантирует, что сценарий завершится, когда что-то вернет false. Тогда с something || true

можно избежать определенного сбоя,
5
ответ дан 22 May 2018 в 21:36

Вы можете попробовать немного поэкспериментировать с запуском скрипта с помощью

#!/bin/bash -e

. -e гарантирует, что сценарий завершится, когда что-то вернет false. Тогда с something || true

можно избежать определенного сбоя,
5
ответ дан 18 July 2018 в 11:45

Самый простой способ сбой при ошибке - использовать опцию -e bash set -e или /bin/bash -e в shebang). Однако это не упрощает отправку пользовательских сообщений об ошибках. Есть несколько идиом, которые могли бы сделать это проще:

die à la Perl

Perl имеет очень удобную команду die, которая печатает сообщение в stderr и создает исключение, которое обычно приводит к завершению сценария. Вы можете эмулировать это:

die () { ret=$? print "%s\n" "$@" >&2 exit "$ret" } false || die "Obvious error because its false on left" true || die "This shouldn't print"

trap ERR

Команда trap <command> может использоваться для запуска команды при получении сигнала или при выходе из script (trap ... EXIT), или когда команда возвращает ошибку (trap ... ERR). Итак, что-то вроде:

trap 'ret=$?; printf "%s\n" "$ERR_MSG" >&2; exit "$ret"' ERR

Тогда:

ERR_MSG="Obvious error because its false here" false ERR_MSG="This shouldn't print" true

В любом случае я бы предложил использовать как минимум exit 1, чтобы указать что сценарий завершился неудачно. Обычная exit будет использовать статус выхода предыдущей команды, которая в этих случаях будет командами echo или printf, которые обычно выполняются. Сохранение статуса выхода команды сбоя, как я сделал здесь, было бы неплохо.

7
ответ дан 18 July 2018 в 11:45

Проблема состоит в том, что || и & amp; & amp; только пропустить одну последующую строфу цепочки команд, когда условие не выполняется. Если вы выписываете полную структуру блока, это имеет смысл. То, что вы написали, становится следующим:

if ! true ; then echo "This shouldn't print" else exit fi

Что вы хотите:

if ! true ; then echo "This shouldn't print" exit fi

Когда вы используете условные операторы быстрого вызова Bash, лучше не смешивать их. Логику намного легче понять, пока вы ее пишете, и ваши читатели оценят ваш хороший стиль.

http://mywiki.wooledge.org/BashGuide/TestsAndConditionals#Control_Operators http: // mywiki .wooledge.org / BashPitfalls # cmd1_.26.26_cmd2_.7C.7C_cmd3
13
ответ дан 18 July 2018 в 11:45

Вы можете попробовать немного поэкспериментировать с запуском скрипта с помощью

#!/bin/bash -e

. -e гарантирует, что сценарий завершится, когда что-то вернет false. Тогда с something || true

можно избежать определенного сбоя,
5
ответ дан 24 July 2018 в 19:51

Самый простой способ сбой при ошибке - использовать опцию -e bash set -e или /bin/bash -e в shebang). Однако это не упрощает отправку пользовательских сообщений об ошибках. Есть несколько идиом, которые могли бы сделать это проще:

die à la Perl

Perl имеет очень удобную команду die, которая печатает сообщение в stderr и создает исключение, которое обычно приводит к завершению сценария. Вы можете эмулировать это:

die () { ret=$? print "%s\n" "$@" >&2 exit "$ret" } false || die "Obvious error because its false on left" true || die "This shouldn't print"

trap ERR

Команда trap <command> может использоваться для запуска команды при получении сигнала или при выходе из script (trap ... EXIT), или когда команда возвращает ошибку (trap ... ERR). Итак, что-то вроде:

trap 'ret=$?; printf "%s\n" "$ERR_MSG" >&2; exit "$ret"' ERR

Тогда:

ERR_MSG="Obvious error because its false here" false ERR_MSG="This shouldn't print" true

В любом случае я бы предложил использовать как минимум exit 1, чтобы указать что сценарий завершился неудачно. Обычная exit будет использовать статус выхода предыдущей команды, которая в этих случаях будет командами echo или printf, которые обычно выполняются. Сохранение статуса выхода команды сбоя, как я сделал здесь, было бы неплохо.

7
ответ дан 24 July 2018 в 19:51

Проблема состоит в том, что || и & amp; & amp; только пропустить одну последующую строфу цепочки команд, когда условие не выполняется. Если вы выписываете полную структуру блока, это имеет смысл. То, что вы написали, становится следующим:

if ! true ; then echo "This shouldn't print" else exit fi

Что вы хотите:

if ! true ; then echo "This shouldn't print" exit fi

Когда вы используете условные операторы быстрого вызова Bash, лучше не смешивать их. Логику намного легче понять, пока вы ее пишете, и ваши читатели оценят ваш хороший стиль.

http://mywiki.wooledge.org/BashGuide/TestsAndConditionals#Control_Operators http: // mywiki .wooledge.org / BashPitfalls # cmd1_.26.26_cmd2_.7C.7C_cmd3
13
ответ дан 24 July 2018 в 19:51
  • 1
    Да, на мой взгляд, это гораздо больше, чем нужно писать в bash – derHugo 13 June 2017 в 08:32
  • 2
    @takatakatek Это делает более понятным, почему это не удается в моем случае. Я согласен с тем, что логика очевидна в этом, но не является причиной для группировки условий с использованием & amp; & amp; и || заключается в том, чтобы не выражать их, используя условные утверждения? – kosol 15 June 2017 в 23:24
  • 3
    @kosol Да, & amp; & amp; & amp; и || объединить две вещи: проверить статус выхода предыдущей команды и указать одну команду (или группу команд), которая будет выполнена (для & amp; & amp;) или пропущена (для ||). Они могут быть полезны для очень простых случаев, но они не могут заменить полностью выраженные блоки if ... then ... elif ... else ... fi. Я подозреваю, что вы, возможно, не знаете, что Bash не имеет истинных типов boolean , которые видны на более сложных языках. Если статус выхода команды равен 0 (ноль), Bash рассматривает это как true / success . Если статус выхода не равен нулю, Bash рассматривает это как false / failure . – takatakatek 16 June 2017 в 01:34

Другие вопросы по тегам:

Похожие вопросы: