你如何杀死所有的子进程不杀死父母 [英] How do you kill all child processes without killing the parent
问题描述
我有在开始运行后台进程的脚本,然后朝最终需要停止后台进程和它的孩子们,然后做一些其他任务等必要时再返回错误code。我该怎么做呢?我已经看到了如何杀死整棵树,包括(如杀0
)父过程中的几个例子,但我想在主脚本继续运行并返回正确的错误code。例如:
./ some_process_with_child_processes&安培;
。/做东西
杀$! #犯规杀子进程!
./do_other_stuff
5号出口
要扩大埃德治愈的评论:
在父进程,陷阱SIGTERM,如:
陷阱回声收到SIGTERMSIGTERM
然后,当你要终止所有的子进程,在主脚本做
杀-s SIGTERM 0
家长也会收到SIGTERM,但是这并不重要,因为它是被困的信号。
您也可能会发现,设置退出陷阱的子进程,使他们能够清理,当他们收到SIGTERM。
您的可能的发送子进程SIGKILL,但是这是一个有点残酷,孩子进程将不会有机会做任何清理。
修改
下面是一些脚本,说明如何父母脚本可以单独杀害其子,而不是使用EN -s SIGTERM集体杀0
。
traptest
#!/斌/庆典#陷阱测试
#写的PM 2Ring 2014年10月23日MYNAME = $(基名$ 0)
孩子= sleeploop
延迟= $ {1:-5}
循环= $ {2:-5}SIG = SIGTERM
#SIG = SIGKILL
#SIG = SIGINT#杀=假signal_children()
{
杀死= TRUE
在IPID$ {的PID [@]}
做
回声发送$ SIG至$ IPID
杀-s $ SIG $ IPID
DONE
}set_INT_trap()
{
味精=回声-e \\\\ n $ MYNAME收到^ C,送$ SIG儿童\\
陷阱$味精; signal_childrenSIGINT
}陷阱回声\\拜拜从$ MYNAME \\EXIT的PID =()
因为我在A B C;做
回声运行$子$ I $延迟......
./$child $ I $延迟和放大器;
PID = $!
#回声-e$儿童$我PID = $ PID \\ n
的PID + =($ PID)
DONE
#回声的所有孩子的PID:$ {PID的[@]}回声$ MYNAME PID = $$
回声; PS;回声set_INT_trap $ SIG
陷阱回声$ MYNAME收到SIGTERM; signal_childrenSIGTERM回声$ MYNAME睡觉......
睡18安培;
等待$!
回声$ MYNAME醒[[$打死=真]!]放大器;&安培; {回声$ MYNAME发送$ SIG signal_children; }回声$ MYNAME完成
sleeploop
#!/斌/庆典#为traptest孩子脚本
#写的PM 2Ring 2014年10月23日MYNAME =$(基名$ 0)$ 1
延迟= $ 16
循环= $ {3} -5set_trap()
{
SIG = $ 1
陷阱回声-e'\\ n $ MYNAME收$ SIG信号';退出0$ SIG
}陷阱回声\\拜拜从$ MYNAME \\EXIT
set_trap SIGTERM
#set_trap SIGINT#选择睡眠模式
如果假
然后
回声利用前景睡眠$ MYNAME
睡觉()
{
睡眠延迟$
}
其他
回声使用后台睡眠$ MYNAME
睡觉()
{
休眠$延迟&放大器;
等待$!
}
科幻#TIME打盹:)
为((i = 0; I<循环;我++));
做
回声$ I:$ MYNAME睡$延时
睡觉
DONE回声$ MYNAME正常终止
这甚至可以,如果你想管 traptest
的输出,例如尝试
{./traptest;回声>和2退出code $ ?; } |猫-n
I have a script which runs a background process at the beginning, then towards the end needs to stop that background process and its children, THEN do some other tasks etc then return an error code if necessary. How do I do this? I have seen several examples of how to kill the whole tree including the parent process (eg kill 0
) but I want the main script to continue running and return the right error code. E.g.:
./some_process_with_child_processes &
./do_stuff
kill $! # doesnt kill child processes!
./do_other_stuff
exit 5
To expand on Ed Heal's comment:
In the parent process, trap SIGTERM, eg
trap "echo received sigterm" SIGTERM
Then, when you want to terminate all the child processes, in the main script do
kill -s SIGTERM 0
The parent will also receive SIGTERM, but that doesn't matter, since it's trapped that signal.
You may also find it useful to set a trap for EXIT in the child processes so they can clean up when they receive SIGTERM.
You could send the child processes SIGKILL, but that's a bit brutal, and the child processes won't have a chance to do any clean up.
edit
Here are some scripts that illustrate how a parent script can kill its children individually, rather than en masse using kill -s SIGTERM 0
.
traptest
#!/bin/bash
# trap test
# Written by PM 2Ring 2014.10.23
myname=$(basename "$0")
child=sleeploop
delay=${1:-5}
loops=${2:-5}
sig=SIGTERM
# sig=SIGKILL
# sig=SIGINT
# killed=False
signal_children()
{
killed=True
for ipid in "${pids[@]}"
do
echo "Sending $sig to $ipid"
kill -s $sig $ipid
done
}
set_INT_trap()
{
msg="echo -e \"\n$myname received ^C, sending $sig to children\""
trap "$msg; signal_children" SIGINT
}
trap "echo \"bye from $myname\"" EXIT
pids=()
for i in A B C;do
echo "running $child $i $delay ..."
./$child $i $delay &
pid=$!
# echo -e "$child$i PID = $pid\n"
pids+=($pid)
done
# echo "all child PIDs: ${pids[@]}"
echo "$myname PID = $$"
echo; ps; echo
set_INT_trap $sig
trap "echo $myname Received SIGTERM; signal_children" SIGTERM
echo "$myname sleeping..."
sleep 18 &
wait $!
echo "$myname awake"
[[ $killed != True ]] && { echo "$myname sending $sig"; signal_children; }
echo "$myname finished"
sleeploop
#!/bin/bash
# child script for traptest
# Written by PM 2Ring 2014.10.23
myname="$(basename "$0")$1"
delay=$2
loops=${3:-5}
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 "$myname using foreground sleep"
Sleep()
{
sleep $delay
}
else
echo "$myname using background sleep"
Sleep()
{
sleep "$delay" &
wait $!
}
fi
#Time to snooze :)
for ((i=0; i<loops; i++));
do
echo "$i: $myname sleeping for $delay"
Sleep
done
echo "$myname terminated normally"
This even works if you want to pipe the output of traptest
, eg try
{ ./traptest; echo >&2 exitcode $?; } | cat -n
这篇关于你如何杀死所有的子进程不杀死父母的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!