하나의 명령이 ERR 트랩을 트리거하는 것을 방지하는 방법은 무엇입니까?

하나의 명령이 ERR 트랩을 트리거하는 것을 방지하는 방법은 무엇입니까?

내 bash 스크립트에서 오류를 포착하고 로그에 발생한 내용을 출력하기 위해 ERR 트랩을 사용하고 있습니다. (이 질문과 유사:트랩, ERR 및 오류 라인 에코) 예상대로 작동합니다. 유일한 문제는 내 스크립트의 어느 시점에서 종료 코드 !=0이 발생할 것으로 예상된다는 것입니다. 이 상황에서 트랩이 작동하지 않게 하려면 어떻게 해야 합니까?

다음은 몇 가지 코드입니다.

err_report() {
    echo "errexit on line $(caller)" | tee -a $LOGFILE 1>&2
}

trap err_report ERR

그런 다음 나중에 스크립트에서 다음을 수행합니다.

<some command which occasionally will return a non-zero exit code>

if [ $? -eq 0 ]; then
    <handle stuff>
fi

명령이 0이 아닌 값을 반환할 때마다 내 트랩이 트리거됩니다. 코드의 이 부분에서만 이 문제를 피할 수 있나요?

이 질문을 확인했습니다.`set -eu` 사용 시 EXIT 및 ERR 트랩의 올바른 동작 그러나 나는 그것을 내 경우에 적용하는 방법을 실제로 알지 못합니다. 적용 가능하다면.

답변1

ERR trap오류 코드가 즉시 "발견"되면 는 트리거되지 않습니다 .~할 수 있다if항상 오류 트래핑을 켜거나 끌 필요 없이 명령문과 기타 등등을 사용하십시오 . 그러나 당신은할 수 없다흐름 제어 검사를 사용하세요 $?. 왜냐하면 검사에 도달할 때 이미 잡히지 않은 오류가 있을 수 있기 때문입니다.

실패할 것으로 예상되는 명령이 있는 경우 - 그리고하지 마라이러한 실패가 를 유발하도록 하려면 trap단순히 실패를 포착하면 됩니다. 이를 명령문으로 표현하는 if것은 투박하고 장황하지만 다음 약어는 훌륭하게 작동합니다.

/bin/false || :  # will not trigger an ERR trap

그러나 명령이 실패할 때 작업을 수행하려면 if여기에서 괜찮습니다.

if ! /bin/false; then
    echo "this was not caught by the trap!"
fi

또는 else오류 상태도 포착합니다.

if /bin/false; then
    : # dead code
else
    echo "this was not caught by the trap!"
fi

요약하자면, 즉각적이고 본질적으로 설명되지 않는 오류 조건이 있는 경우에만 트립됩니다 set -e.trap "command" ERR

답변2

ERR필요에 따라 코드 부분에서 트랩을 활성화/비활성화할 수 있습니다 .

#!/bin/bash
err_report() {
    echo "errexit on line $(caller)"
}
trap err_report ERR
trap - ERR             # disable ERR trap
false
if [ $? -eq 0 ]; then
    printf "OK\n"
else
    printf "FAIL\n"    # prints FAIL
fi
trap err_report ERR    # enable ERR trap
false                  # prints errexit on line 14

답변3

나는 종종 ERR 트랩을 피하고 싶지만 내 함수의 반환 코드도 폐기하고 싶지 않습니다. 그래서 제가 사용하는 패턴은 다음과 같습니다.

RC=0
some_function || RC=$?

그런 다음 RC에 필요한 모든 작업을 수행합니다.

답변4

트랩 ERR은 와 동일한 규칙을 따릅니다 set -e. 즉, 조건으로 사용되는 명령에는 적용되지 않습니다. 그래서,

trap "echo error" ERR
false                     # this should trigger the trap
if ! false; then          # this shouldn't
     echo handle stuff
fi

조건 의 명령은 다음과 if같을 수 있음 을 기억하십시오.어느명령일 필요는 없습니다 [ .. ]. 따라서 명령의 종료 상태에 대한 true/false 평가만 원하는 경우 조건에서 직접 사용하면 됩니다 if.

종료 코드를 저장해야 하는 경우그리고함정 을 피하려면 ERR다음과 같은 작업을 수행해야 합니다.

somecmd && :; ret=$?

여기서는 트랩 &&을 스쿼시 ERR하지만 종료 코드가 0인 경우에만 실행되므로 종료 코드가 와 동일하다는 것을 알 수 있습니다 :.

확인하고 싶을 수도 있습니다BashFAQ 105: set -e(또는 set -o errexit 또는 트랩 ERR)가 예상한 대로 작동하지 않는 이유는 무엇입니까?

관련 정보