bash 如何通过脚本集合传播信号?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2525855/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to propagate a signal through a collection of scripts?
提问by Debugger
I have an collection of scripts which are controlled by a main one. I want to trap the signal ctrl+cin the main script and propagate it to the others. The other scripts should trap this signal as well ( from the main script ) and do some clean-up ...
我有一组由主要脚本控制的脚本。我想在主脚本中捕获信号ctrl+c并将其传播给其他脚本。其他脚本也应该捕获这个信号(来自主脚本)并做一些清理......
I have tried to send kill -s SIGINTto the children, but they seem they are unable to catch the signal( even if trap 'Cleanup' SIGINTbeing defined on the children scripts )
我试图发送kill -s SIGINT给孩子们,但他们似乎无法捕捉到信号(即使trap 'Cleanup' SIGINT在孩子们的脚本中定义)
Any clues how to realize this?
任何线索如何实现这一点?
回答by lhunath
The following example demonstrates a parent script that does something (sleep 5) after it starts two children that do their own thing (also sleep 5). When the parent exits (for whatever reason) it signals the children to terminate (don't SIGINT, termination is signaled by SIGTERM, also the default killsignal). The children then do their thing on reception of SIGTERM. If the children are scripts of their own, I recommend you change the trap on TERMinto a trap on EXITso that the children clean up no matter what the cause of their termination be (so long as it's trappable).
下面的示例演示了一个父脚本,它sleep 5在启动两个执行自己的操作(也sleep 5)的子项之后执行某些操作 ( )。当父级退出(无论出于何种原因)时,它会向子级发出终止信号(不要SIGINT,终止由 发出信号SIGTERM,也是默认kill信号)。孩子们然后在接待处做他们的事情SIGTERM。如果孩子是他们自己的脚本,我建议您将陷阱更改TERM为陷阱,EXIT以便孩子们无论终止的原因是什么(只要它是可捕获的)都会清理。
Notice my use of wait. Bash does not interrupt running non-builtin commands when it receives a signal. Instead, it waits for them to complete and handles the signal after the command is done. If you use wait, bash stops waiting immediately and handles the signal right away.
请注意我对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
回答by Julien Palard
Have you tried to : 1) Setup your traps in every script (master / childs) where you need them 2) Send to the master a kill with it's PID negated, to kill the whole process group, I mean :
您是否尝试过:1)在需要它们的每个脚本(主/子)中设置您的陷阱 2)向主发送一个杀死它的 PID 否定,杀死整个进程组,我的意思是:
kill -15 -$PID
man kill | grep -C1 Negative
人杀| grep -C1 否定
回答by MattyV
MAIN PARENT SCRIPT HEADER BEFORE THE MAIN LOOP:::
主循环前的主父脚本头::
#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
}
In the main body of the script, as you spawn subprocesses you maintain an array with the proc ids of each. To load the PID into the array set the value to last spawned process e.g. put the following after each sub-shell spawn.
在脚本的主体中,当您生成子进程时,您会维护一个包含每个子进程的 proc id 的数组。要将 PID 加载到数组中,请将值设置为上次生成的进程,例如在每个子壳生成后放置以下内容。
proc_id_array[1]=$!
Contents of the M_shutdow would be something like...
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
}
回答by Cascabel
I'm not sure what do you mean by "other scripts should trap this signal from the main script"? How can a subprocess script use code in the main script to trap a signal?
我不确定“其他脚本应该从主脚本捕获这个信号”是什么意思?子进程脚本如何使用主脚本中的代码来捕获信号?
I don't want to try and write much code for you because I don't know exactly what you mean by "scripts controlled by a main one" either, but presumably you launch some subprocesses then have a control loop which checks if the other scripts have exited, and can grab their exit status? If that's the case, the thing that makes the most sense to me is for each script to do its own trapping and cleanup. When the main script traps a signal, it can if desired pass the signal along to all the children (via kill -s <signal> pid). When a child process traps a signal, it can return an exit status indicating that it was terminated by that signal. The main can then handle that exit status appropriately - perhaps in the same way as if it'd received that particular signal itself. (Shell functions are your friend.)
我不想尝试为您编写太多代码,因为我也不知道“由主程序控制的脚本”究竟是什么意思,但大概您启动了一些子进程然后有一个控制循环来检查另一个脚本已经退出,并且可以获取它们的退出状态?如果是这种情况,对我来说最有意义的事情是让每个脚本都进行自己的捕获和清理。当主脚本捕获信号时,如果需要,它可以将信号传递给所有子进程(通过kill -s <signal> pid)。当子进程捕获信号时,它可以返回退出状态,指示它已被该信号终止。然后 main 可以适当地处理该退出状态 - 可能就像它自己接收到该特定信号一样。(外壳函数是你的朋友。)

