2つのプロセスの簡単な例があります。
最初は、いくつかの処理を実行する単純なループです。
#!/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