Настройка параметра bash pipefail
(через set -o pipefail
) позволяет script сбой, если обнаружена ненулевая ошибка, где на любом этапе трубы есть ненулевая ошибка.
Однако мы сталкиваемся с ошибками SIGPIPE
(код ошибки 141), где данные записываются в канал, который больше не существует.
Есть ли способ установить bash игнорировать ошибки SIGPIPE
или есть подход к написанию обработчика ошибок, который будет обрабатывать все коды состояния ошибки, но, скажем, 0 и 141?
Например, в Python мы можем добавить:
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
применить поведение по умолчанию к ошибкам SIGPIPE
: игнорировать их (см. http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-06/3823.html).
Есть ли аналогичная опция в bash?
Команда trap
позволяет указать команду для запуска, когда встречается сигнал. Чтобы игнорировать сигнал, пропустите пустую строку:
trap '' PIPE
Я обрабатываю это по каждому конвейеру, привязывая к оператору || if ...
для проглатывания кода выхода 141, но все еще сталкиваясь с любыми другими ошибками:
pipe | that | fails || if [[ $? -eq 141 ]]; then true; else exit $?; fi
set -e
( set -o errexit
) также используется, это можно сократить до pipe | that | fails || test $? -eq 141
(+ некоторые обязательные комментарии, конечно, объясняющие магическое число).
Я не знаю, как это сделать для всего script. Это было бы рискованно в целом, так как нет способа узнать, что детский процесс не возвратил 141 по другой причине.
Но вы можете сделать это на основе каждой команды. Оператор ||
подавляет любые ошибки, возвращенные первой командой, поэтому вы можете сделать что-то вроде:
set -e -o pipefail
(cat /dev/urandom || true) | head -c 10 | base64
echo 'cat exited with SIGPIPE, but we still got here!'
pipefail
? Если это так, то как бы проверить код ошибки по сигналу, который был поднят, чтобы я могcontinue
на 0 и 141?SIGPIPE
, оставляя другие сигналы без изменений.