대시와 ksh 및 bash의 출구 트랩

대시와 ksh 및 bash의 출구 트랩

다음은 현재 디렉토리에 임시 디렉토리를 설정하고 종료 시 이를 삭제하는 트랩을 설정하는 간단한 스크립트입니다.

#filename: script   
set -x  
trap 'rm -rf "$d"' exit
d=`TMPDIR=$PWD mktemp -d`
"$@"

ksh script sleep 100또는 bash script sleep 100으로 중단 하면 C-C트랩이 실행되고 디렉토리가 삭제됩니다. 에서는 작동하지 않습니다 dash. 왜? 이것은 버그입니까, 아니면 의도된 동작입니까?

답변1

zsh, pdksh(최신 버전은 아니지만 mksh) yash, Bourne 쉘은 dash.

bash, ksh88및 만 다르게 동작 ksh93합니다 mksh.

SIGINTPOSIX 사양은 올바른 동작이 무엇인지 명확하지 않지만 쉘이 (또는 다른) 신호 에 대한 기본 핸들러를 재정의할 수 있다는 내용은 없습니다 .

EXIT트랩 작업이 호출될 때 평가되어야 한다고 말하지만 AFAICT는 예를 들어 구문 오류 또는 특수 내장 실패와 같은 오류 조건 exit의 결과로 쉘이 종료될 때 평가되어야 하는지조차 말하지 않습니다 .set -eset -u

EXIT신호 수신 시 트랩을 실행할 수 있으려면 쉘이 해당 신호에 핸들러를 설치해야 합니다.

그것이 바로 ksh, mksh그리고 bash하는 일이지만, 그들이 처리하는 신호 목록은 세 가지 구현 모두에서 다릅니다. 3 개 모두에 공통되는 유일한 신호는 INT, QUIT, 및 입니다 .TERMALRMHUP

EXIT일부 신호에 대해 트랩을 실행 하려면 이식 가능한 방법은 해당 신호를 직접 처리하는 것입니다.

trap 'exit 1' INT HUP QUIT TERM ALRM USR1
trap 'cleanup' EXIT

그러나 이 접근 방식은 트랩 핸들러에서 호출되는 경우 트랩을 zsh실행하지 않는 에서는 작동하지 않습니다 .EXITexit

또한 신호로 사망 사실을 부모에게 보고하지 못합니다.

대신에 다음을 수행할 수 있습니다.

for sig in INT QUIT HUP TERM ALRM USR1; do
  trap "
    cleanup
    trap - $sig EXIT
    kill -s $sig "'"$$"' "$sig"
done
trap cleanup EXIT

이제 실행하는 동안 더 많은 신호가 도착하면 가 cleanup다시 cleanup실행될 수 있다는 점에 유의하세요. 여러 번 호출하면 올바르게 작동하는지 확인 cleanup하거나 실행 중에 신호를 무시할 수 있습니다.

답변2

경고: exit작동이 보장되지 않습니다. 대신 사용해야 합니다.EXIT

POSIX 표준은 EXIT신호의 경우에도 트랩을 실행해야 하는지 여부를 정의하지 않고 EXIT언급한 경우 Bourne Shell이 ​​트랩을 호출하지 않는다는 사실을 고려하면 다음을 입력하는 것이 분명합니다.불특정행동.

관련 정보