các ERR
bẫy không phải là để chạy mã khi vỏ bản thân thoát ra với một mã lỗi khác không, nhưng khi bất kỳ lệnh chạy bằng vỏ rằng đó không phải là một phần của một điều kiện (như trong if cmd...
, hoặc cmd || ...
...) thoát với một tổ chức phi-zero trạng thái thoát (cùng điều kiện với những gì gây set -e
ra thoát khỏi vỏ).
Nếu bạn muốn chạy mã khi thoát khỏi shell với trạng thái thoát khác không, bạn nên thêm một cái bẫy EXIT
thay vào đó và kiểm tra $?
ở đó:
trap '[ "$?" -eq 0 ] || echo hi' EXIT
Tuy nhiên, xin lưu ý rằng khi có tín hiệu bị bẫy, cả bẫy tín hiệu và bẫy EXIT sẽ được chạy, do đó bạn có thể muốn thực hiện như sau:
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
Hoặc để sử dụng trạng thái thoát như $((signum + 128))
tín hiệu:
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
Tuy nhiên, lưu ý rằng việc thoát bình thường khi SIGINT hoặc SIGQUIT có các tác dụng phụ khó chịu tiềm ẩn khi quy trình cha mẹ của bạn là một vỏ như thế bash
thực hiện việc chờ đợi và xử lý thoát hợp tác của ngắt thiết bị đầu cuối. Vì vậy, bạn có thể muốn đảm bảo tự giết mình bằng tín hiệu tương tự để báo cáo với cha mẹ rằng bạn thực sự bị gián đoạn, và nó cũng nên xem xét việc tự thoát ra nếu nó nhận được 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
Nếu bạn muốn ERR
bẫy bắn, chỉ cần chạy một lệnh với trạng thái thoát khác không như false
hoặc test
.