Cách kích hoạt lỗi bằng lệnh Bẫy


13

Tôi đang sử dụng Ubuntu 12.04.2. Tôi đang cố gắng sử dụng lệnh "bẫy" để ghi lại bất thường hoặc lỗi trong tập lệnh shell của mình nhưng tôi cũng đang cố gắng tự kích hoạt thoát "Lỗi".

Tôi đã thử thoát 1, nhưng nó sẽ không kích hoạt tín hiệu "Lỗi".

#!/bin/bash

func()
{
    exit 1
}

trap "echo hi" INT TERM ERR
func

Không chắc chắn làm thế nào để kích hoạt thủ công tín hiệu thoát "Lỗi"?

Câu trả lời:


20

các ERRbẫ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 -era 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 EXITthay 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ế bashthự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 ERRbẫ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ư falsehoặc test.


6

Sử dụng lại, không xuất cảnh, để thiết lập trạng thái trên thoát khỏi một chức năng (nếu chức năng rơi qua mà không có một sự trở lại, tình trạng là các báo cáo kết quả cuối cùng thực hiện.) Nếu bạn thay thế returncho exittrong ví dụ của câu hỏi, nó sẽ làm việc như Tôi nghĩ bạn đã dự định: bẫy sẽ được kích hoạt trên tín hiệu giả ERR và 'hi' sẽ được in. Để xem xét thêm, hãy thử điều này:

#!/bin/bash

func()
{
    echo 'in func'
    return 99
    echo 'still in func'
}

trap 'echo "done"' EXIT
trap 'status=$?; echo "error status is $status"; trap - EXIT; exit $status' ERR
func
echo 'returned from func'

Bạn có thể thử nhiều sửa đổi khác nhau, chẳng hạn như trả về 0, nhận xét bẫy ERR, không hủy bẫy EXIT trong trình xử lý ERR, không thoát khỏi trình xử lý ERR hoặc xóa trả về và đưa ra falsetuyên bố cuối cùng trong func.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.