我有一组由主要脚本控制的脚本。我想在主脚本中捕获信号ctrl+c并将其传播给其他脚本。其他脚本也应该捕获这个信号(来自主脚本)并进行一些清理......
我试图发送kill -s SIGINT
给孩子们,但他们似乎无法捕捉到信号(即使trap 'Cleanup' SIGINT
是在孩子们的脚本上定义的)
任何线索如何实现这一点?
我有一组由主要脚本控制的脚本。我想在主脚本中捕获信号ctrl+c并将其传播给其他脚本。其他脚本也应该捕获这个信号(来自主脚本)并进行一些清理......
我试图发送kill -s SIGINT
给孩子们,但他们似乎无法捕捉到信号(即使trap 'Cleanup' SIGINT
是在孩子们的脚本上定义的)
任何线索如何实现这一点?
下面的示例演示了一个父脚本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)在您需要它们的每个脚本(主/子)中设置您的陷阱 2)向主发送一个杀死它的 PID 否定,以杀死整个进程组,我的意思是:
kill -15 -$PID
男人杀| grep -C1 否定
主循环之前的主父脚本标题:::
#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
}
在脚本的主体中,当您生成子进程时,您会维护一个数组,其中包含每个子进程的 proc id。要将 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
}
我不确定“其他脚本应该从主脚本中捕获这个信号”是什么意思?子进程脚本如何使用主脚本中的代码来捕获信号?
我不想尝试为您编写太多代码,因为我也不确切知道“由主要脚本控制的脚本”是什么意思,但大概您启动了一些子进程然后有一个控制循环来检查另一个脚本已经退出,并且可以获取它们的退出状态?如果是这样的话,对我来说最有意义的是每个脚本都进行自己的捕获和清理。当主脚本捕获信号时,如果需要,它可以将信号传递给所有子脚本(通过kill -s <signal> pid
)。当子进程捕获一个信号时,它可以返回一个退出状态,表明它已被该信号终止。然后 main 可以适当地处理该退出状态 - 可能就像它自己接收到该特定信号一样。(Shell 函数是你的朋友。)