bash `set -e` сбрасывает внутренние функции при запуске через` $ (...) `? - PullRequest
2 голосов
/ 04 октября 2019

Кажется, что опция set -e в Bash сбрасывается внутри функций, когда эти функции вызываются с помощью расширения $(...).

Это меня удивляет, и я не уверен, что это так. ошибка или нет. Я не смог найти описание этого поведения на (обычно довольно тщательной) странице руководства Bash.

Примечание: вот некоторые другие подобные сообщения SO:

Но ни одна из них не имеет отношения к $(...), который на самом деле не обсуждается на странице руководства.

Я также не могу найти ссылку на эту проблему в превосходном Bash FAQ 105 .

Вот небольшая программачтобы продемонстрировать проблему:

echo "Initial:    $-"
set -eu
echo "After set:  $-"

function foo() {
    echo "Inside foo: $-"
}
foo

function bar() {
    false    # I'd expect this to immediately fail
    echo "Inside bar: $-"
}
# When a $(...) construct is involved, 'bar' runs to completion!
x=$(bar)
echo "We should never get here ... but we do."
echo "$x"

Для меня, на Bash версии 5.0.11(0)-release, я получаю следующий вывод:

Initial:    hB
After set:  ehuB
Inside foo: ehuB
We should never get here ... but we do.
Inside bar: huB

Итак, как вы можете видеть, -uОпция во всех случаях передается функции. И опция -e пропускается, когда функция вызывается нормально. Но только в особом случае $(bar) опция -e сбрасывается.

Кто-нибудь знает, является ли это документированным поведением или иным образом объяснимым?

Это не имеет смысла для меня(

Ответы [ 2 ]

4 голосов
/ 04 октября 2019

Поведение set -e в сочетании с Подстановка команд задокументировано в Среде выполнения команд :

Подоболочки, порожденные для выполнения подстановок команд, наследуютзначение параметра -e из родительской оболочки. Когда не в режиме POSIX, Bash очищает опцию -e в таких подоболочках.

Это говорит о том, что поведение, которое вы видите, является ожидаемым - если вы не работаете в режиме POSIX, * 1014Параметр * не установлен в подоболочках подстановки команд в Bash (хотя параметр -e изначально наследуется, он изменяется вскоре после того, как подоболочка начинает выполнение). Это забавный способ написать это.

3 голосов
/ 04 октября 2019

Соответствующие цитаты страницы man для вас, сначала из раздела Подстановка команд .

Подстановка команд позволяет выводу команды заменить имя команды. Существует две формы:

         $(command)
   or
         `command`

Bash выполняет раскрытие, выполняя команду в среде подоболочек и заменяя подстановку команды стандартным выводом команды, удаляя все завершающие символы новой строки.

И из Среда выполнения команд :

Подоболочки, созданные для выполнения подстановок команд, наследуют значение опции -e из родительской оболочки. Когда не в режиме posix, bash очищает опцию -e в таких подоболочках.

Так что bar выполняется в подоболочке, и, поскольку вы не находитесь в режиме posix, -eОпция очищается.

Добавьте set -o posix в начало вашего скрипта, и он будет работать так, как ожидалось, хотя ожидайте других отличий при использовании этого режима.

...