특정 명령이 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: -e를 설정(또는 -o errexit 또는 트랩 ERR을 설정)해도 예상한 대로 작동하지 않는 이유는 무엇입니까?

관련 정보