วิธีการทริกเกอร์ข้อผิดพลาดโดยใช้คำสั่ง Trap


13

ฉันใช้ Ubuntu 12.04.2 ฉันพยายามใช้คำสั่ง "trap" เพื่อจับภาพผิดปกติหรือข้อผิดพลาดในเชลล์สคริปต์ของฉัน แต่ฉันยังพยายามที่จะออกจาก "Error" ด้วยตนเอง

ฉันลองใช้ทางออก 1 แล้ว แต่จะไม่ส่งสัญญาณ "ข้อผิดพลาด"

#!/bin/bash

func()
{
    exit 1
}

trap "echo hi" INT TERM ERR
func

ไม่แน่ใจว่าจะเรียกสัญญาณออก "ผิดพลาด" ด้วยตนเองได้อย่างไร

คำตอบ:


20

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ดักไฟเพียงแค่เรียกใช้คำสั่งที่มีสถานะทางออกที่ไม่ใช่ศูนย์เหมือน หรือfalsetest


6

กลับใช้ไม่ได้ออกจากการตั้งค่าสถานะเมื่อออกจากฟังก์ชั่น (ถ้ามีฟังก์ชั่นตกผ่านโดยไม่ต้องกลับสถานะเป็นที่ของคำสั่งที่ผ่านมาดำเนินการ.) หากคุณใช้แทนreturnสำหรับexitในตัวอย่างของคำถามก็จะทำงานเป็น ฉันคิดว่าคุณตั้งใจ: กับดักจะถูกทริกเกอร์ในสัญญาณหลอก ERR และ 'สวัสดี' จะถูกพิมพ์ สำหรับข้อควรพิจารณาเพิ่มเติมลองสิ่งนี้:

#!/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'

คุณสามารถลองปรับเปลี่ยนต่าง ๆ เช่นส่งคืน 0 แสดงความคิดเห็นกับดัก ERR ไม่ยกเลิกกับดัก EXIT ภายใน ERR handler ไม่ออกจาก ERR handler หรือลบการคืนและวางfalseเป็นคำสั่งสุดท้ายใน func

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.