INT와 ERR이 모두 캡처되지만 콜백이 여러 번 실행됩니다.

INT와 ERR이 모두 캡처되지만 콜백이 여러 번 실행됩니다.

다음 코드를 사용하여 INT 및 ERR을 캡처합니다.

set -ex -o pipefail

dest=$(mktemp -d)
cd "$dest"

trap "echo; echo Clean up; rm -rf $dest" INT ERR
sleep 9999

클린 콜백을 누르면 ^C여러 번 실행됩니다.

++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
++ echo

++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516

이것이 예상되는 동작입니까? 한번만 가능할까요?

답변1

INT 및 ERR 신호를 모두 수신합니다. SIGINT는 sleep0이 아닌 반환 코드로 종료됩니다. 0이 아닌 반환 코드는 SIGERR 트랩을 트리거합니다.

sigspec이 ERR인 경우 파이프라인(단일 단순 명령으로 구성될 수 있음), 목록 또는 복합 명령이 0이 아닌 종료 상태를 반환할 때마다 arg... 명령이 실행됩니다.

개별 트랩을 살펴보는 예:

set -ex -o pipefail
trap "echo Clean up for INT" INT
trap "echo Clean up for ERR" ERR
sleep 9999

실행한 다음 Ctrl-C를 누르세요.

+ trap 'echo Clean up for INT' INT
+ trap 'echo Clean up for ERR' ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ echo Clean up for ERR
Clean up for ERR

트랩을 한 번만 호출하는 경우 한 가지 옵션은 트랩 ERR내에서 트랩을 재설정하는 것입니다.INT

...
trap "echo Clean up for INT; trap ERR" INT ERR
...

...결과는 다음과 같습니다.

+ trap 'echo Clean up for INT; trap ERR' INT ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ trap ERR

답변2

에서는 bash간단히 로 대체할 수 있습니다 trap "my-cleanup-command" EXIT. 이 트랩은 SIGINT가 전송될 때를 포함하여 스크립트가 종료될 때 실행됩니다. 제 생각에는 이것이 일반적으로 더 우아한 접근 방식입니다 ...

bash에만 해당된다는 사실을 제외하면. EXIT 트랩은 POSIX에 언급되어 있지만 해당 동작은 지정되지 않았습니다. 다른 많은 쉘에서는 신호로 인해 쉘이 종료되면 EXIT 트랩이 실행되지 않습니다.

https://unix.stackexchange.com/a/57960/29483

나는 때때로 쉘 스크립트를 정말 싫어합니다 :).


연결된 답변을 보면 첫 번째 트랩 이후 코드가 실행되지 않도록 하는 덜 bash 관련 방법은 즉시 종료하는 것입니다. 이를 위해 다른 방법을 사용할 수도 있지만 이것이 제가 시도해 볼 수 있는 가장 간단한 방법입니다.

cleanup() {
    echo "Clean up"
    rm -rf "$dest"
}
trap cleanup EXIT
trap "exit 1" INT ERR

관련 정보