Trap 명령을 사용하여 오류를 트리거하는 방법

Trap 명령을 사용하여 오류를 트리거하는 방법

우분투 12.04.2를 사용하고 있습니다. 쉘 스크립트에서 예외나 오류를 포착하기 위해 "trap" 명령을 사용하려고 하지만 수동으로 "error" 종료를 트리거하려고 합니다.

Exit1을 시도했지만 "오류" 신호가 발생하지 않습니다.

#!/bin/bash

func()
{
    exit 1
}

trap "echo hi" INT TERM ERR
func

"오류" 종료 신호를 수동으로 트리거하는 방법을 모르시나요?

답변1

함정 ERR은 셸 자체가 0이 아닌 오류 코드로 종료될 때 코드를 실행하는 것이 아니라, 셸이 0이 아닌 명령을 실행할 때 코드를 실행하는 것입니다.상황( if cmd...또는 cmd || ......에서와 같이) 0이 아닌 종료 상태로 종료합니다( set -e셸이 종료되도록 한 것과 동일한 조건).

셸을 종료할 때 0이 아닌 종료 상태로 코드를 실행하려면 트랩을 추가 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

하지만 상위 프로세스가 다음 과 같은 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같이 0이 아닌 종료 상태로 명령을 실행하면 됩니다 .falsetest

답변2

함수가 종료될 때 상태를 설정하려면exit 대신 return을 사용하십시오(함수가 return하지 않고 실패하면 상태는 마지막으로 실행된 명령문의 상태입니다.) 질문의 예를 대체하면 다음과 같이 작동할 것 같습니다 return. exit당신의 의도는 ERR 스퓨리어스 신호에서 트랩이 실행되고 "hi"가 인쇄되는 것입니다. 추가 고려사항이 있는 경우 다음을 시도해 보세요.

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

false0 반환, ERR 트랩 주석 처리, ERR 핸들러에서 EXIT 트랩 취소 안 함, ERR 핸들러에서 종료 안 함, return 제거 및 func의 마지막 문으로 만드는 등 다양한 수정을 시도할 수 있습니다.

관련 정보