sigterm의 bash 동작

sigterm의 bash 동작

아래와 같은 스크립트를 작성하세요.

#!/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포함 하여 지정된 명령을 실행합니다 .rmexit
  • 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 트랩( echorm) 실행을 마치면, 쉘은 종료하는 것 외에는 할 일이 없습니다. 유일한 질문은 스크립트가 어떤 종료 상태로 종료되는지입니다. 그리고 일부 종료 상태 값을 저장하고 수행하는 경우 rm $PIDFILE; exit $saved_status흥미로울 수 있습니다. 하지만 에 대해 이야기하는 한 rm $PIDFILE; exit $?스크립트는 아마도 rm; 의 종료 상태로 종료될 것입니다. 그리고 이것이 rm실행한 마지막 명령인 경우 기본적으로 발생할 수 있습니다 .

나는 이 기능을 중단하는 것이 가능하다는 것을 제안하는 몇 가지 간단한 테스트를 수행했습니다.

trap "exit" INT TERM

명령을 내리는데 그게 이해가 안 돼요. YMMV.


PS Thomas가 말했듯 trap … KILL이 효과가 없습니다.

관련 정보