다음 코드를 사용하여 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는 sleep
0이 아닌 반환 코드로 종료됩니다. 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