ERR
ловушка не для запуска кода , когда сама оболочка выходит с ненулевым кодом ошибки, но когда любая команда запуска этой оболочки , которая не является частью состояния (например , в if cmd...
, или cmd || ...
...) выходит с ненулевым состояние выхода (те же условия, что и set -e
при выходе из оболочки).
Если вы хотите запускать код при выходе из оболочки с ненулевым статусом выхода, вы должны EXIT
вместо этого добавить ловушку и проверить $?
там:
trap '[ "$?" -eq 0 ] || echo hi' EXIT
Тем не менее, обратите внимание, что при перехваченном сигнале будут работать как ловушка сигнала, так и ловушка EXIT, поэтому вы можете сделать это следующим образом:
unset killed_by
trap 'killed_by=INT;exit' INT
trap 'killed_by=TERM;exit' TERM
trap '
ret=$?
if [ -n "$killed_by" ]; then
echo >&2 "Ouch! Killed by $killed_by"
exit 1
elif [ "$ret" -ne 0 ]; then
echo >&2 "Died with error code $ret"
fi' EXIT
Или использовать статус выхода, как $((signum + 128))
по сигналам:
for sig in INT TERM HUP; do
trap "exit $((128 + $(kill -l "$sig")))" "$sig"
done
trap '
ret=$?
[ "$ret" -eq 0 ] || echo >&2 "Bye: $ret"' EXIT
Однако обратите внимание, что обычный выход из SIGINT или SIGQUIT имеет потенциальные раздражающие побочные эффекты, когда ваш родительский процесс представляет собой оболочку, подобную bash
этой, которая реализует ожидание и совместную обработку выхода терминального прерывания. Таким образом, вы можете захотеть убить себя тем же сигналом, чтобы сообщить родителям о том, что вы действительно прерваны, и что он также должен рассмотреть возможность выхода из себя, если получил SIGINT / SIGQUIT.
unset killed_by
for sig in INT QUIT TERM HUP; do
trap "exit $((128 + $(kill -l "$sig"))); killed_by=$sig" "$sig"
done
trap '
ret=$?
[ "$ret" -eq 0 ] || echo >&2 "Bye: $ret"
if [ -n "$killed_by" ]; then
trap - "$killed_by" # reset handler
# ulimit -c 0 # possibly disable core dumps
kill -s "$killed_by" "$$"
else
exec "$ret"
fi' EXIT
Если вы хотите, чтобы ERR
ловушка сработала, просто запустите команду с ненулевым статусом выхода, например false
или test
.