Bash: ловушка ERR не работает, когда используется оператор трубы

Я пытаюсь записать все, что выходит из stdout и stderr, в файл журнала и при этом сохранить консоль. Для этого я просто добавил: |& tee -a log_file.log к каждой команде.
Тем не менее, я также хочу запустить пользовательскую команду, если во время сценария произошла какая-либо ошибка. Для этого я добавил следующее в начале скрипта: trap "echo Non-zero exit code detected" ERR,
Проблема в том, что при использовании оператора pipe эхо в ловушке больше не выполняется.

Сценарий 1, без трубы:

$cat test.sh
#!/bin/bash

trap "echo Non-zero exit code detected!" ERR

function fail_please()
{
    echo "Returning non-zero exit code!"
    return 1
}

fail_please 

Выход 1:

$ ./test.sh 
Returning non-zero exit code!
Non-zero exit code detected!

Сценарий 2, с трубкой:

$ cat test.sh
#!/bin/bash

trap "echo Non-zero exit code detected!" ERR

function fail_please()
{
    echo "Returning non-zero exit code!"
    return 1
}

fail_please |& tee log_file.log 

Выход 2:

$ ./test.sh
Returning non-zero exit code!
$ cat log_file.log 
Returning non-zero exit code!

На выходе 2 появляется сообщение "Обнаружен ненулевой код выхода!" пропал, отсутствует. Есть идеи почему? Спасибо!

1 ответ

Решение

ERR ловушка для "простых команд" конвейер - не простая команда.

Это может сработать для результата всего конвейера (я не уверен), и вы можете получить что-то ближе к тому, что вы хотите, установив pipefail,

(Примечание: это одна из причин, по которой люди часто не рекомендуют использовать set -e как это имеет удивительные детали, как это.)

Причина pipefail работает то, что обычно возвращаемое состояние конвейера - это возвращение последней команды, но с pipefail на это становится статусом возврата последней команды, которая терпит неудачу.

Состояние возврата конвейера - это состояние выхода последней команды, если не включена опция pipefail. Если pipefail включен, состояние возврата конвейера - это значение последней (самой правой) команды для выхода с ненулевым статусом или ноль, если все команды завершаются успешно.

Другие вопросы по тегам