Я использую set -e
дляостановить bash-скрипт при первой ошибке.
Все работает нормально, пока я не использую команду с &&
:
$ 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. Похожий вопрос:https://stackoverflow.com/questions/6930295/set-e-and-short-tests
решение1
Это задокументированное поведение.bash(1) страница руководстваговорит, дляset -e
,
Оболочка не завершает работу, если команда, которая не выполняется, является частью списка команд, следующей сразу за ключевым словом
while
илиuntil
, частью теста, следующей за зарезервированными словамиif
или ,elif
часть любой команды, выполняемой в списке&&
или||
за исключением команды, следующей за финальным&&
или||
, любая команда в конвейере, кроме последней, или если возвращаемое значение команды инвертируется с помощью!
.
[Выделено мной.]
ИPOSIXЯзык команд оболочкиСпецификация подтверждает, что это правильное поведение:
Настройка
-e
будет игнорироваться при выполнении списка составных элементов, следующего за зарезервированным словомwhile
,until
,if
, илиelif
конвейером, начинающимся с!
зарезервированного слова, или любой командой списка И-ИЛИ, кроме последней.
иРаздел 2.9.3Спискиэтого документа определяет
Список И-ИЛИ представляет собой последовательность одного или нескольких конвейеров, разделенных операторами «
&&
» и «||
».
решение2
В некоторых ситуациях эта 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'
Theподоболочкане выполняется в составной команде:
(false; echo 'not printed') | cat -; echo printed
решение3
Я предполагаю, что условие if-then в целом оценивается как истинное.
Я пытался
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
Код ошибки перехватывается условием if, поэтому bash не вызовет завершение выполнения.