SIGTERM bash 트랩 실패

SIGTERM bash 트랩 실패

신호를 포착하는 매우 간단한 스크립트가 있습니다.

#!/bin/bash                                                                     
unlink SigTermRecieved
unlink SigIntRecieved
#trap " touch SigTermRecieved ; exit " SIGTERM                                  
trap " touch SigIntRecieved ; exit " SIGINT
echo "pid is $$"
while true
do
    sleep 60m
done
exit

행동

두 트랩 라인 모두 주석 처리됩니다:
SIGTERM Sent: Terminate program.
? 다른 터미널 창에서 보낸 SIGINT가 무시되었습니다!
CTRL C는 프로그램을 종료합니다.

SIGTERM 트랩은 주석 처리되지 않습니다.
? SIGTERM 전송됨: 프로그램이 종료되지 않으며 SIGTERM 트랩이 실행되지 않습니다.
? 다른 터미널 창에서 보낸 SIGINT가 무시되었습니다!
CTRL C는 프로그램을 종료합니다.

주석 처리되지 않은 SIGINT 트랩:
SIGTERM 전송됨: 프로그램을 종료합니다.
? 다른 터미널 창의 SIGINT가 무시되었습니다!
CTRL C는 트랩 코드를 실행하고 프로그램을 종료합니다.

이전 행동? 예상치 못한 일이거나 잘못된 일입니다. 나는 SIGINT 동작에 별로 관심이 없습니다. 나는 함정 중 하나가 작동하는지 확인하기 위해 이것을 시도했습니다.

그래서 스누즈 기능을 제거하고 다음과 같이 했습니다.

sleep 60m &
wait $!

이제 kill -TERM -pid두 프로세스를 모두 종료하고 SIGTERM 트랩을 실행하십시오.

내 애플리케이션에서는 일부 세부 정보를 정리할 수 있도록 시스템이 종료될 때 SIGTERM을 기다리고 있습니다. 시스템 종료가 사용되었는지 pid여부는 알 수 없습니다 -pid. 둘 다 저에게 효과적이며 시스템은 결국 모든 프로세스를 종료합니다. 테스트하는 동안 몇 가지 매달린 수면 과정은 큰 문제가 아니었습니다.

fifo에 대한 솔루션은 매우 복잡해서 이해가 되지 않습니다.

도와주셔서 감사합니다.

답변1

[아래 설명에서 bash(또는 다른 쉘)은 C 프로그램이라는 점을 기억하십시오. 스크립트가 트랩을 설정하지 않더라도 신호에 대한 핸들러를 설정할 수 있습니다.]

두 트랩 라인 모두 주석 처리되어 있습니다.
SIGTERMSent: Terminate Program.

bash핸들러가 설정되지 않았기 때문에 SIGTERM이 신호는 이를 완전히 종료하여 이를 시작한 쉘이 프롬프트로 돌아가게 합니다. 그러나 sleep외부 프로그램이고 별도의 하위 프로세스에서 실행되는 명령은 ( pgrep -a sleep확인을 위해) 계속 실행됩니다.

? SIGINT다른 터미널 창에서 보낸 메시지는 무시됩니다!

sleep이 경우 와 같이 하위 프로세스를 기다릴 때 bash에 대한 신호 처리기를 설정하고 SIGINT트랩이 설정되지 않은 경우 해당 신호를 무시합니다. 단, 동일한 신호로 인해 기다리고 있는 하위 프로세스가 종료되는 경우는 제외됩니다. . bash신호에 의해 종료되었는지, 어떤 신호인지를 자식의 종료 상태로부터 수집할 수 있습니다.

이것을 "기다리고 협력하여 나가기"라고 합니다(세계교육협의회SIGINT) 및 신호 에만 적용됩니다 SIGQUIT.

SIGINT다른 쉘은 이를 수행하지 않을 수 있으며, 기다리고 있는 하위 프로세스가 종료될 때까지 신호에 대한 조치를 지연할 수 있습니다 . 합계 bash비교의 예 dash:

$ ( (sleep .2; pkill -INT -P $$)&); dash -c 'while :; do /bin/sleep 3; done'
<dash is killed by a self-raised SIGINT after 3 seconds>

$ ( (sleep .2; pkill -INT -P $$)&); bash -c 'while :; do /bin/sleep 3; done'
^C
<bash has to be killed by hand with Control-C>

CTRL C프로그램을 종료합니다.

A는 Ctrl-C원인이 될 것입니다핵심SIGINT신호 보내기모두포그라운드 프로세스 그룹(작업)의 프로세스. 이 경우에는 다음이 포함됩니다.둘 다귀하의 스크립트와 sleep해당 첨자. kill다음 명령을 사용하여 이를 시뮬레이션할 수 있습니다 .부정적인PID프로세스팀장(프로세스 그룹 ID와 동일) 또는 kill작업 ID와 함께 내장 셸을 사용합니다.

bash -c 'sleep 3600; echo DONE' &
[1] 12381
kill -INT -12381  # or kill -INT %1

스크립트의 음수 pid는 다음과 같은 경우에만 사용하세요.프로세스팀장. 스크립트가 서브셸이나 다른 스크립트에서 호출되거나 파이프라인의 일부로 호출되는 경우에는 그렇지 않을 수 있습니다.

트랩은 SIGTERM주석 처리되지 않습니다.
? SIGTERM전송됨: 프로그램이 종료되지 않았고 SIGTERM트랩이 실행되지 않았습니다.

예, 트랩이 실행됩니다. 단, sleep주문이 종료된 후에만 가능합니다. 확인을 위해 60분을 기다리지 않으려면 sleep 1대신 사용하세요 ;-)sleep 60m

이것은 연결된 답변에서도 설명됩니다. 여기에는표준 요구 사항행동.

함정은 주석 SIGINT처리되지 않았습니다.
? SIGINT다른 터미널 창의 메시지는 무시됩니다!

같은 상기와.

답변2

간단한 해결책을 찾았습니다.

function snooze {
    sleep $1
}

while true
do
    snooze 60m &
    wait $!
done

이는 트랩을 실행한 다음 SIGTERM을 수신하는 즉시 종료됩니다.

도와 주셔서 감사합니다.

관련 정보