Это код в a.sh (команда foo недоступна, это намеренная ошибка):
#!/bin/bash
set -ex
{
foo
echo 1
} || echo 2
Я ожидаю, что он напечатает 2, но он печатает это:
$ ./a.sh
+ foo
./a.sh: line 5: foo: command not found
+ echo 1
1
Почему и как это исправить? Я знаю, что могу соединить foo и echo 1 с &&, но я ожидаю, что set -e выполнит эту работу.
1 не следует печатать (из-за сбоя в foo)
Итак, исходя из этого, строка echo 1 должна быть if [ "$?" = "0" ] then; echo 1 else echo 2 fi после ошибки foo.
Поведение set -e очень неинтуитивно (и даже несовместимо между различными версиями bash) — никогда не рассчитывайте на то, что он сделает что-то разумное! См. BashFAQ 105: «Почему set -e (или set -o errexit, или ловушка ERR) не делает то, что я ожидал?»
Re «Я ожидаю, что set -e выполнит работу»: из-за MO bash (смешение отчетов об ошибках с условными выражениями) реализация set -e в лучшем случае неясна. Используйте его для удобства (например, чтобы лучше определить причину ошибки), но никогда не заставляйте свой код полагаться на него.





Можно написать такой код:
score=0
if ((score)); then
echo not zero
else
echo zero
fi
((0)) возвращается 1, но очевидно, что ошибки нет.
Вот почему мы никогда не ожидаем, что set -e завершит выполнение сценария, когда команда возвращает ненулевое значение в условном тесте.
Почему bash не завершает выполнение сценария после ошибки внутри скобок?
Потому что команда является частью конвейера ||, в котором set -e действует.
Но это терпит неудачу. Почему бы и нет?