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 включен, состояние возврата конвейера - это значение последней (самой правой) команды для выхода с ненулевым статусом или ноль, если все команды завершаются успешно.