쉘 스크립트가 시작될 때 감지하기는 쉽지만 언제 중지되는지 알기가 항상 쉬운 것은 아닙니다. 스크립트는 작성자가 의도한 대로 정상적으로 종료될 수 있지만 예기치 않은 치명적인 오류로 인해 실패할 수도 있습니다. 스크립트가 실패했을 때 진행 중이던 모든 것을 그대로 유지하는 것이 좋을 때도 있고 불편할 때도 있습니다. 어느 쪽이든, 스크립트의 끝을 감지하고 미리 계산된 방식으로 이에 반응하기 때문에 Bash trap
지시문이 존재합니다.
실패 대응
다음은 스크립트에서 한 번의 실패가 어떻게 미래의 실패로 이어질 수 있는지에 대한 예입니다. /tmp
에 임시 디렉토리를 생성하는 프로그램을 작성했다고 가정해 보겠습니다. 파일을 다른 형식으로 다시 묶기 전에 보관을 취소하고 처리할 수 있도록:
#!/usr/bin/env bash
CWD=`pwd`
TMP=${TMP:-/tmp/tmpdir}
## create tmp dir
mkdir "${TMP}"
## extract files to tmp
tar xf "${1}" --directory "${TMP}"
## move to tmpdir and run commands
pushd "${TMP}"
for IMG in *.jpg; do
mogrify -verbose -flip -flop "${IMG}"
done
tar --create --file "${1%.*}".tar *.jpg
## move back to origin
popd
## bundle with bzip2
bzip2 --compress "${TMP}"/"${1%.*}".tar \
--stdout > "${1%.*}".tbz
## clean up
/usr/bin/rm -r /tmp/tmpdir
대부분의 경우 스크립트는 예상대로 작동합니다. 그러나 예상한 JPEG 파일 대신 PNG 파일로 채워진 아카이브에서 실수로 실행하면 중간에 실패합니다. 하나의 실패는 다른 실패로 이어지며 결국 스크립트는 임시 디렉토리를 제거하라는 최종 지시에 도달하지 않고 종료됩니다. 디렉토리를 수동으로 제거하기만 하면 빠르게 복구할 수 있지만 그렇게 할 수 없다면 다음에 스크립트가 실행될 때 예측할 수 없는 남은 파일로 가득 찬 기존 임시 디렉토리를 처리해야 합니다.피>
이를 방지하는 한 가지 방법은 스크립트 시작 부분에 예방적 제거를 추가하여 논리를 뒤집고 이중화하는 것입니다. 유효하지만 구조 대신 무차별 대입에 의존합니다. 보다 우아한 솔루션은 trap
입니다. .
트랩으로 신호 잡기
trap
키워드는 신호를 포착합니다. 실행 중에 발생할 수 있습니다. kill
을 사용한 적이 있다면 이러한 신호 중 하나를 사용한 것입니다. 또는 killall
SIGTERM
을 호출하는 명령 기본적으로. 쉘이 응답하는 다른 많은 신호가 있으며 대부분은 trap -l
로 볼 수 있습니다. ("목록"에서와 같이):
$ trap --list
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
이러한 신호는 trap
으로 예상할 수 있습니다. . 이 외에도 trap
인식:
EXIT
:쉘 프로세스 자체가 종료될 때 발생ERR
:명령(예:tar 또는 mkdir ) 또는 기본 제공 명령(예:pushd 또는 cd ) 0이 아닌 상태로 완료됨DEBUG
:디버그 모드를 나타내는 부울
Bash에서 트랩을 설정하려면 trap
을 사용하세요. 그 다음에는 실행하려는 명령 목록, 트리거할 신호 목록이 옵니다.
예를 들어, 이 트랩은 SIGINT
를 감지합니다. , 사용자가 Ctrl+C를 누를 때 전송되는 신호 프로세스가 실행되는 동안:
trap "{ echo 'Terminated with Ctrl+C'; }" SIGINT
임시 디렉토리 문제가 있는 예제 스크립트는 트랩 감지 SIGINT
로 수정할 수 있습니다. , 오류 및 성공적인 종료:
#!/usr/bin/env bash
CWD=`pwd`
TMP=${TMP:-/tmp/tmpdir}
trap \
"{ /usr/bin/rm -r "${TMP}" ; exit 255; }" \
SIGINT SIGTERM ERR EXIT
## create tmp dir
mkdir "${TMP}"
tar xf "${1}" --directory "${TMP}"
## move to tmp and run commands
pushd "${TMP}"
for IMG in *.jpg; do
mogrify -verbose -flip -flop "${IMG}"
done
tar --create --file "${1%.*}".tar *.jpg
## move back to origin
popd
## zip tar
bzip2 --compress $TMP/"${1%.*}".tar \
--stdout > "${1%.*}".tbz
복잡한 작업의 경우 trap
을 단순화할 수 있습니다. Bash 함수가 있는 문.
Bash의 트랩
트랩은 스크립트가 성공적으로 실행되는지 여부에 관계없이 스크립트가 깔끔하게 종료되도록 하는 데 유용합니다. 자동화된 가비지 수집에 완전히 의존하는 것은 결코 안전하지 않으므로 일반적으로 사용하는 것이 좋습니다. 스크립트에서 사용해 보고 무엇을 할 수 있는지 확인하십시오!