신호를 포착하는 매우 간단한 스크립트가 있습니다.
#!/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 프로그램이라는 점을 기억하십시오. 스크립트가 트랩을 설정하지 않더라도 신호에 대한 핸들러를 설정할 수 있습니다.]
두 트랩 라인 모두 주석 처리되어 있습니다.
SIGTERM
Sent: 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을 수신하는 즉시 종료됩니다.
도와 주셔서 감사합니다.