두 가지 프로세스에 대한 간단한 예가 있습니다.
첫 번째는 일부 처리를 수행하는 간단한 루프입니다.
#!/bin/bash
function signalHandler() {
echo "sig: $1 received ==> exit"
for i in {1..5}; do
echo "cleanup $i %"
sleep 1
done
trap SIGINT
kill -INT $$
}
trap signalHandler SIGUSR2
for i in {1..100000}; do
echo "doing stuff $i %"
sleep 0.1
done
나는 다음과 같이 스크립트를 시작했습니다.
./script.sh | grep "wow"
데모를 위해 보조 grep 명령을 첨부했습니다.
grep
USR2 신호 ( )만 프로세스에 보내면 kill USR2 $(pgrep grep)
파이프 전체가 찢어집니다(?). 계속하지 않겠 습니까 script.sh
?
둘째, USR2 신호를 전체 프로세스 그룹에 보낼 때도 동일한 일이 발생합니다(예 ?kill USR2 -$!
Operation:grep
script.sh
signalHandler
감사합니다
답변1
@muru가 언급했듯이 문제는 스크립트가 SIGPIPE
.
다음 변경 사항을 사용하면 스크립트가 예상대로 종료될 수 있습니다.
function signalHandler() {
echo "sig: $1 received ==> exit" >&2 # <--
for i in {1..5}; do
echo "cleanup $i %" >&2 # <--
sleep 1
done
trap SIGINT
kill -INT $$
}
trap signalHandler SIGUSR2
trap signalHandler SIGPIPE # <--
예제를 단순하게 유지하기 위해 동일한 신호 처리기가 처리에 사용됩니다 SIGPIPE
. echo
신호 처리기의 출력은 잡히면 분명히 파괴되기 STDERR
때문에 리디렉션됩니다 .STDOUT
SIGPIPE
산출:
$ ./script.sh | grep wow
./script.sh: line 16: echo: write error: Broken pipe
sig: received ==> exit
cleanup 1 %
cleanup 2 %
cleanup 3 %
cleanup 4 %
cleanup 5 %
User defined signal 2: 31
파이프가 끊어졌지만(첫 번째 오류 메시지) 신호 처리기가 script.sh
종료되기 전에 완료됩니다.
이를 완전히 무시하려면 SIGPIPE
신호에 대한 더미 핸들러를 추가하고 echo
기본 문의 STDERR을 다음으로 리디렉션 해야 합니다 /dev/null
.
function signalHandler2() {
:
}
trap signalHandler SIGUSR2
trap signalHandler2 SIGPIPE
# ...skip...
for i in {1..100000}; do
echo "doing stuff $i %" 2>/dev/null