Почему Bash не передает опцию errexit для командных замен?

Почему Bash не передает опцию errexit для командных замен?

Параметры оболочки, заданныеsetвстроенныйнаследуются в подоболочках (по крайней мере errexit). Это может быть доказано:

set -o errexit

function foo() {
    echo "foo:$BASHPID"
    false
    echo 'after' 
}

echo "main:$BASHPID"
( foo )

Однако, похоже, эти варианты не наследуютсязамена команды, которые также должны быть подоболочками согласно документации Bash. Доказательство:

set -o errexit

function foo() {
    echo "foo:$BASHPID"
    false
    echo 'after' 
}

echo "main:$BASHPID"
output=$(foo)
echo "output: $output"

Ожидаемый результат:

main:123
output: foo:124

Фактический результат:

main:123
output: foo:124
after

Это ожидаемо или ошибка?

решение1

Да, как и ожидалось, когда bash не находится в режиме POSIX (например, при запуске от имени ), он по умолчанию shсбрасывает внутренние подстановки команд.errexit

Если вы хотите errexitсохранить данные внутри подстановок команд, в bash 4.4 или более поздней версии используйте:

inherit_errexit

Если установлено, подстановка команд наследует значение параметра errexit, а не отменяет его в среде подоболочки. Этот параметр включен, когда включен режим POSIX.

(ОтРуководство по Башу.)Еще часть из документациисделал это более явным:

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

Проверять:

$ bash -o errexit -c 'echo "$(echo "$SHELLOPTS")"'
braceexpand:hashall:interactive-comments
$ bash -o errexit -O inherit_errexit -c 'echo "$(echo "$SHELLOPTS")"'
braceexpand:errexit:hashall:interactive-comments

В bash 4.2 и более ранних версиях errexitотображалось в первом варианте, но по-прежнему фактически отключено:

$ bash-4.2 -o errexit c 'echo "$(false; echo "$SHELLOPTS")"'
braceexpand:errexit:hashall:interactive-comments
$ bash-4.2 -o posix -o errexit -c 'echo "<$(false; echo "$SHELLOPTS")> $?"'
<> 1

Связанный контент