我有一个由主要脚本控制的脚本集合。我想在主脚本中捕获信号 ctrl + c 并将其传播给其他人。其他脚本也应该捕获此信号(来自主脚本)并进行一些清理......
我试图向孩子发送kill -s SIGINT
,但他们似乎无法捕捉到信号(即使在儿童脚本上定义了trap 'Cleanup' SIGINT
)
任何线索如何实现这一点?
答案 0 :(得分:19)
以下示例演示了一个父脚本在启动两个执行自己操作的子节点(sleep 5
)之后执行某些操作(sleep 5
)。当父母退出时(无论出于何种原因),它指示孩子终止(不SIGINT
,终止由SIGTERM
发出信号,也是默认的kill
信号。然后孩子们在接待SIGTERM
时做他们的事情。如果这些孩子是他们自己的脚本,我建议你将TERM
上的陷阱改为EXIT
上的陷阱,以便孩子们无论其终止的原因是什么都可以清理(只要它是可捕获的)。
请注意我使用wait
。 Bash在收到信号时不会中断运行的非内置命令。相反,它在命令完成后等待它们完成并处理信号。如果你使用wait
,bash会立即停止等待并立即处理信号。
#!/usr/bin/env bash
trap 'echo parent shutting down; kill $(jobs -p)' EXIT
{ trap 'echo child 1 signaled' TERM; sleep 5 & wait; } &
{ trap 'echo child 2 signaled' TERM; sleep 5 & wait; } &
sleep 5
答案 1 :(得分:4)
你试过: 1)在您需要的每个脚本(主/子)中设置陷阱 2)发送给主人一个杀死它的PID否定,杀死整个进程组,我的意思是:
kill -15 -$PID
人杀了grep -C1否定
答案 2 :(得分:0)
主循环前的主要脚本脚本:::
#Catch control-c and clean up testd instances if necessary
cleanup () {
clear
echo "Caught Signal. Shutting Down MAIN."
if [ "$MAIN_on" -eq 1 ]
then
M_shutdown
fi
exit 1
}
在脚本的主体中,当您生成子进程时,您将维护一个包含每个子进程的数组。要将PID加载到数组中,请将值设置为上次生成的进程,例如在每个子shell生成后放置以下内容。
proc_id_array[1]=$!
M_shutdow的内容将类似......
M_shutdown () {
if [ "$MAIN_on" -eq 1 ]
then
echo "Stopping Main"
echo "shutting down active subscripts"
count_proc_id=1
while [ "$count_proc_id" -lt "$max_proc_id" ]
do
kill ${proc_id_array[$count_proc_id]} > /dev/null 2>&1
DATE=$(date +%m%d%y-%k:%M)
echo "$DATE: ${proc_name_array[$count_proc_id]} \(PID: ${proc_id_array[$count_proc_id]}\) stopped." >> $logfile
proc_id_array[$count_proc_id]="A"
count_proc_id=`expr $count_proc_id + 1`
done
echo "MAIN stopped"
MAIN_on=0
sleep 5
else
echo "MAIN already stopped."
sleep 1
fi
}
答案 3 :(得分:-1)
我不确定你的意思是“其他脚本应该从主脚本中捕获这个信号”?子进程脚本如何使用主脚本中的代码来捕获信号?
我不想尝试为你编写很多代码因为我不确切地知道“主要控制的脚本”究竟是什么意思,但是大概是你启动了一些子进程然后有一个控制循环来检查如果其他脚本已退出,并可以获取其退出状态?如果是这种情况,对我来说最有意义的是每个脚本都要进行自己的捕获和清理。当主脚本捕获信号时,如果需要,它可以将信号传递给所有孩子(通过kill -s <signal> pid
)。当子进程捕获信号时,它可以返回退出状态,指示它已被该信号终止。然后,主要可以适当地处理该退出状态 - 可能与它收到该特定信号本身的方式相同。 (Shell函数是你的朋友。)