아래와 같은 스크립트를 작성하세요.
#!/bin/bash
#
# run this script. don't run it if it's already running.
#
PIDFILE=/tmp/script.pid
LOGFILE=script.log
if [[ -f $PIDFILE ]]; then
echo "$PIDFILE exists. Not going to run..."
exit 0
fi
sleep 10m >> $LOGFILE 2>&1 &
PID=$!
echo $PID > $PIDFILE
trap "echo Exiting...; rm $PIDFILE; exit $?" INT TERM EXIT KILL
wait $PID
이 스크립트를 아래와 같이 호출합니다.
timeout 2m ./test_script
시간 초과 또는 Ctrl+C 시 스크립트는 "Exiting"을 두 번 인쇄합니다.
# timeout 2m ./test_script
^CExiting...
Exiting...
rm: cannot remove `/tmp/script.pid': No such file or directory
다음은 strace 및 추가 데이터의 출력입니다.
# ps -ef | grep -v grep | egrep -i "sleep|time"
root 8571 4690 0 12:17 pts/0 00:00:00 timeout 2m ./test_script
root 8572 8571 0 12:17 pts/0 00:00:00 /bin/bash ./test_script
root 8573 8572 0 12:17 pts/0 00:00:00 sleep 10m
# cat /tmp/script.pid
8573
# strace -p 8571
Process 8571 attached - interrupt to quit
wait4(-1, 0x7fffc43fad4c, 0, NULL) = ? ERESTARTSYS (To be restarted)
--- SIGINT (Interrupt) @ 0 (0) ---
kill(0, SIGINT) = 0
kill(0, SIGCONT) = 0
--- SIGCONT (Continued) @ 0 (0) ---
rt_sigreturn(0) = 61
--- SIGINT (Interrupt) @ 0 (0) ---
rt_sigreturn(0x2) = 61
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 8572
--- SIGCHLD (Child exited) @ 0 (0) ---
close(1) = 0
close(2) = 0
exit_group(0) = ?
Process 8571 detached
스크립트가 "Exiting..."을 2번 인쇄하기 위해 신호를 두 번 트랩하는 이유에 대한 내부 이해를 도와줄 수 있는 사람이 있습니까?
답변1
trap
명령문을 다음 세 줄로 바꾸면 :
trap "echo Exiting... INT; exit $?" INT
trap "echo Exiting... TERM; exit $?" TERM
trap "echo Exiting... EXIT; exit $?" EXIT
당신은 출력을 얻을 것이다
Exiting... TERM
Exiting... EXIT
우리가 추론할 수 있는 것
- 명령문은
trap … TERM
쉘이 SIGTERM 신호를 트랩하도록 합니다. 이timeout
명령은 제한 시간이 만료되면 프로세스에 SIGTERM(기본값)을 보냅니다. 따라서 쉘은 신호를 포착하고 , (실제 스크립트에서) 및 를echo
포함 하여 지정된 명령을 실행합니다 .rm
exit
- 이
trap … EXIT
명령문은 쉘이 "집에 가기 전에 이 작업을 수행하도록 기억하세요"라는 스티커 메모를 남기도록 합니다. 따라서 SIGTERM 트랩이exit
명령을 실행하면 EXIT 트랩이 실행됩니다. - EXIT 트랩이
exit
명령을 실행하면 EXIT 트랩을 실행하고 재귀 지옥으로 들어가는 것이 아니라 실제로 스크립트가 종료됩니다.
Ctrl스크립트가 실행되는 동안 +를 입력하면 CINT 트랩과 EXIT 트랩이 차례로 표시됩니다. 가 없거나 timeout
절전 시간보다 긴 시간 초과 기간을 사용하여 스크립트를 실행하면 EXIT 트랩만 표시됩니다.
아마 말해도 충분할 것 같아요
trap "exit $?" INT TERM
trap "echo Exiting...; rm $PIDFILE" EXIT
나는 EXIT 트랩을 실행할 필요가 없다고 생각합니다 exit
. 왜냐하면 명령을 실행하여 EXIT 트랩에 들어가기 때문입니다 exit
(스크립트 끝에 암시적인 명령 포함). 따라서 EXIT 트랩( echo
및 rm
) 실행을 마치면, 쉘은 종료하는 것 외에는 할 일이 없습니다. 유일한 질문은 스크립트가 어떤 종료 상태로 종료되는지입니다. 그리고 일부 종료 상태 값을 저장하고 수행하는 경우
rm $PIDFILE; exit $saved_status
흥미로울 수 있습니다. 하지만 에 대해 이야기하는 한 rm $PIDFILE; exit $?
스크립트는 아마도 rm
; 의 종료 상태로 종료될 것입니다. 그리고 이것이 rm
실행한 마지막 명령인 경우 기본적으로 발생할 수 있습니다 .
나는 이 기능을 중단하는 것이 가능하다는 것을 제안하는 몇 가지 간단한 테스트를 수행했습니다.
trap "exit" INT TERM
명령을 내리는데 그게 이해가 안 돼요. YMMV.
PS Thomas가 말했듯 trap … KILL
이 효과가 없습니다.