Сценарій Bash з `set -e` не зупиняється на команді`… && ... `


14

Я використовую set -eдля зупинки bash script при першій помилці .

Все працює добре, якщо я не використовую команду з &&:

$ cat script
set -e
cd not_existing_dir && echo 123
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
I'm running! =P
$

в порівнянні з:

$ cat script
set -e
cd not_existing_dir
echo "I'm running! =P"
$
$ ./script
./script: line 2: cd: not_existing_dir: No such file or directory
$

Перший приклад все ще перегукується I'm running!, а другий - ні. Чому вони поводяться по-різному?

UPD. Подібне запитання: /programming/6930295/set-e-and-short-tests


Що ви очікуєте, що станеться в першому прикладі?
Flup

@Flup Я очікую, що сценарій зупиниться після невдалої cdкоманди
907-го,

1
Дивіться BashFAQ # 105 для загального обговорення місць, де set -eповедінка дивує.
Чарльз Даффі

Відповіді:


10

Це документоване поведінка. Сторінка " bash (1)" каже, що для set -e,

Оболонка не виходить , якщо команда , яка не є частиною списку команд відразу після появи whileабо untilключового слово, частина тесту , слідуючи ifабо elifзарезервовані слова, частина будь-якої команди , виконаної в &&або ||списку , крім команди після останньої &&або|| будь-який команда в конвеєрі, але остання, або якщо зворотне значення команди інвертується !.
[Наголос додано.]

І специфікація мови командної оболонки POSIX підтверджує, що це правильна поведінка:

-eУстановка повинна ігноруватися при виконанні з'єднання списку після while, until, ifабо elifзарезервованого слова, трубопровід , починаючи з !зарезервованим словом, або будь-яка команда з І-АБО списку, крім останньої.

та Розділ 2.9.3 Списки цього документа визначають

Список AND-OR - це послідовність одного або декількох трубопроводів, розділених операторами " &&" і " ||".


9

Цей set -eпараметр не має ефекту в деяких ситуаціях, і це стандартна поведінка і портативний через оболонку, сумісну з POSIX.


Невдала команда є частиною конвеєра:

false | true; echo printed

надрукує printed.

І вважається лише вихід з ладу самого трубопроводу:

true | false; echo 'not printed'

нічого не надрукує.


Невдала команда запуску в списку з'єднання після while, until, if, elifзарезервоване слово, трубопровід , починаючи з !зарезервованим словом, або який - або команди в складі &&або ||списку , за винятком останнього:

false || true; echo printed

Остання команда не вдається досі set -eвплинути:

true && false; echo 'not printed'

Подоболочка зазнає невдачі в з'єднанні команди:

(false; echo 'not printed') | cat -; echo printed

Дякую! Ясніше було б використовувати echo "printed"і echo "not_printed"у ваших прикладах (замість echo 1).
907.

3
Зверніть увагу, що set -eвикликає вихід у (false && true); echo not here, але не в { false && true; }; echo here, хоча YMMV з різними оболонками та навіть різними версіями однієї оболонки. Я б не торкався set -eбаржикового стовпа, а замість цього зробив би правильну обробку помилок.
Стефан Шазелас

1

я здогадуюсь, якщо тоді умова в цілому оцінити справжньою.

я намагався

set -e
if cd not_existing_dir
then  echo 123
fi
echo "I'm running! =P"

хто дає

-bash: cd: not_existing_dir: No such file or directory
I'm running! =P

код помилки вловлюється, якщо умова, таким чином, bash не призведе до завершення виконання.


Але я не користуюсяif ... fi
907-го,

Я знаю, це неявне, якщо.
Архемар
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.