f01のコメントで述べたように、子プロセスにSIGTERMを送信する必要があります。以下に、^ Cをトラップして子プロセスにシグナルを送信する方法を示すスクリプトをいくつか示します。
まず、親。
トラップテスト
#!/bin/bash
# trap test
# Written by PM 2Ring 2014.10.23
myname=$(basename "$0")
child=sleeploop
set_trap()
{
sig=$1
msg="echo -e \"\n$myname received ^C, sending $sig to $child, $pid\""
trap "$msg; kill -s $sig $pid" SIGINT
}
trap "echo \"bye from $myname\"" EXIT
echo "running $child..."
./$child 5 &
pid=$!
# set_trap SIGINT
set_trap SIGTERM
echo "$child pid = $pid"
wait $pid
echo "$myname finished waiting"
そして今、子供。
スリープループ
#!/bin/bash
# child script for traptest
# Written by PM 2Ring 2014.10.23
myname=$(basename "$0")
delay="$1"
set_trap()
{
sig=$1
trap "echo -e '\n$myname received $sig signal';exit 0" $sig
}
trap "echo \"bye from $myname\"" EXIT
set_trap SIGTERM
set_trap SIGINT
#Select sleep mode
if false
then
echo "Using foreground sleep"
Sleep()
{
sleep $delay
}
else
echo "Using background sleep"
Sleep()
{
sleep "$delay" &
wait $!
}
fi
#Time to snooze :)
for ((i=0; i<5; i++));
do
echo "$i: sleeping for $delay"
Sleep
done
echo "$myname terminated normally"
traptestがSIGTERMを送信する場合、物事はうまく動作しますが、traptestがSIGINTを送信する場合、sleeploopはそれを認識しません。
sleeploopがSIGTERMをトラップし、スリープモードがフォアグラウンドの場合、現在のスリープから復帰するまでシグナルに応答できません。ただし、スリープモードがバックグラウンドの場合、すぐに応答します。
set -m
。setsid
子を実行するたびに使用するよりも少しクリーンでシンプルです。