Согласно man bash
,
set -e
Выйти немедленно, если (отрывок). Ловушка на ERR
, если установлена, выполняется до выхода из оболочки.
Однако приведенный ниже скрипт не вызывает ловушку ERR
.
trap 'echo ERR; sleep 1' ERR
trap 'echo EXIT; sleep 1' EXIT
set -e
array=(a b c)
echo $(( ${#array[@] - 1)) #note the closing bracket } is forgotten
echo "after"
Ожидаемый результат:
$ bash script.sh
4.sh: line 7: ${#array[@] - 1: bad substitution
ERR
EXIT
# and then shell exits
Фактический результат:
$ bash script.sh
4.sh: line 7: ${#array[@] - 1: bad substitution
EXIT
# and then shell exits
Если я удалю строку set -e
, то
$ bash script2.sh
4.sh: line 7: ${#array[@] - 1: bad substitution
after #the last echo command is executed
EXIT
Это означает set -e
ловит синтаксическую ошибку. Почему не вызывается ловушка ERR
, хотя оболочка не завершает работу?
Среда:
Я тестировал скрипт на двух машинах.
$ bash --version
GNU bash, version 4.4.12(1)-release (arm-unknown-linux-gnueabihf)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ bash --version
GNU bash, version 5.0.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Дополнение:
Согласно опубликованным ответам, вполне естественно, что ловушка не выполняется, и это потому, что echo $(( ${#array[@] - 1))
не завершает свое выполнение, чтобы вернутьсястатус выхода. Правильно ли мое понимание?
Однако man bash
объясняет set -e
как
Немедленно завершить работу, если конвейер (который может состоять из одной простой команды), список илисоставная команда (см. ОБРАЗЕЦ ОБОЛОЧКИ выше), выход с ненулевым статусом.
Я думаю, что для этого также требуется выполнение команды. Если echo $(( ${#array[@] - 1))
не завершит свое выполнение, я считаю, что set -e
здесь не должно работать, а echo "after"
должно быть выполнено.
Дополнение 2:
Согласно Комментарий oguz ismail , это проблема с документацией. POSIX говорит, что set -e
должен выйти из оболочки, когда
и ошибка оболочки включает синтаксическую ошибку . Но в man bash
отсутствует объяснение второго случая, верно? Если это так, все согласуется, за исключением того факта, что man bash
не объясняет реализацию точно и утверждения «Это те же условия, которым подчиняется опция errexit
(-e
)». найдено в объяснении trap
в man bash
.