Я наблюдаю странное поведение при использовании set -e( errexit), set -u( nounset) вместе с ловушками ERR и EXIT. Они кажутся взаимосвязанными, поэтому разумно их объединить.
1) set -uне запускает ERR-ловушки
Код:
#!/bin/bash trap 'echo "ERR (rc: $?)"' ERR set -u echo ${UNSET_VAR}- Ожидается: вызов ERR, RC! = 0
- Фактически: ERR-ловушка не вызывается , RC == 1
- Примечание:
set -eне меняет результат
2) Использование set -euкода выхода в ловушке EXIT 0 вместо 1
Код:
#!/bin/bash trap 'echo "EXIT (rc: $?)"' EXIT set -eu echo ${UNSET_VAR}- Ожидается: вызывается EXIT trap, RC == 1
- Фактически: ловушка EXIT называется, RC == 0
- Примечание. При использовании
set +eRC == 1. Ловушка EXIT возвращает правильный RC, когда любая другая команда выдает ошибку. - Редактировать: есть SO сообщение на эту тему с интересным комментарием, предполагающим, что это может быть связано с используемой версией Bash. Тестирование этого фрагмента с помощью Bash 4.3.11 дает RC = 1, так что это лучше. К сожалению, в настоящее время обновление Bash (с версии 3.2.51) на всех хостах невозможно, поэтому нам нужно найти какое-то другое решение.
Кто-нибудь может объяснить любое из этих поведений?
Поиск по этим темам был не очень успешным, что довольно удивительно, учитывая количество постов в настройках и ловушках Bash. Хотя есть одна ветка форума , но вывод довольно неудовлетворительный.
set -eи set -uоба предназначены специально для уничтожения скриптовой оболочки. Использование их в условиях, которые могут вызвать их приложение, приведет к уничтожению скриптовой оболочки. Нет ничего, кроме как не использовать их, а вместо этого проверять те условия, когда они применяются в последовательности кода. Таким образом, вы можете написать хороший шелл-код или использовать его set -eu.
-uбы не вызвать прерывание ERR (это ошибка, поэтому не следует запускать прерывание) или код ошибки 0 вместо 1. последнее похоже на ошибку, которая уже была исправлена в более поздней версии, вот и все. Но первую часть довольно сложно понять, если вы не поняли, что ошибки в оценке оболочки (расширение параметров) и реальные ошибки в командах кажутся двумя разными вещами. Что касается решения, ну, как вы предложили, я сейчас пытаюсь избежать -euи проверять вручную, когда это необходимо.
(set -u; : $UNSET_VAR)и тому подобное. Подобные вещи тоже могут быть хорошими - вы можете время от &&времени отбрасывать множество вещей : (set -e; mkdir dir; cd dir; touch dirfile)если вы поняли мой дрейф. Просто это контролируемые контексты - когда вы устанавливаете их как глобальные параметры, вы теряете контроль и становитесь контролируемыми. Однако обычно есть более эффективные решения.
bashпорвал со стандартом и начал ставить ловушки в подоболочки. Предполагается, что ловушка будет выполняться в той же среде, откуда пришло возвращение, ноbashона этого не делала довольно давно.