Linux 如何在不杀死父进程的情况下杀死所有子进程
我有一个脚本,它在开始时运行后台进程,然后在结束时需要停止后台进程及其子进程,然后执行一些其他任务等,如果需要,然后返回一个错误代码。我该怎么做?我已经看到了几个如何杀死整个树的示例,包括父进程,例如kill 0,但是我希望主脚本继续运行并返回正确的错误代码。例如:Linux 如何在不杀死父进程的情况下杀死所有子进程,linux,bash,unix,Linux,Bash,Unix,我有一个脚本,它在开始时运行后台进程,然后在结束时需要停止后台进程及其子进程,然后执行一些其他任务等,如果需要,然后返回一个错误代码。我该怎么做?我已经看到了几个如何杀死整个树的示例,包括父进程,例如kill 0,但是我希望主脚本继续运行并返回正确的错误代码。例如: ./some_process_with_child_processes & ./do_stuff kill $! # doesnt kill child processes! ./do_other_stuff exit 5
./some_process_with_child_processes &
./do_stuff
kill $! # doesnt kill child processes!
./do_other_stuff
exit 5
您需要捕获美元的价值!孩子刚出生就死了
/some_process_with_child_processes &
pid=$!
./do_stuff
kill $pid
./do_other_stuff
要扩展Ed Heal的评论,请执行以下操作: 在父进程中,trap SIGTERM,例如 接收到的陷阱回波信号sigterm sigterm 然后,当您想要终止所有子进程时,在主脚本中 kill-s SIGTERM 0 父级也将接收SIGTERM,但这并不重要,因为它捕获了该信号 您可能还发现在子进程中设置一个退出陷阱很有用,这样子进程在收到SIGTERM时就可以进行清理 您可以发送子进程SIGKILL,但这有点残酷,而且子进程没有机会进行任何清理 编辑 下面是一些脚本,它们演示了父脚本如何单独杀死其子脚本,而不是使用kill-s SIGTERM 0集体杀死 traptest 睡眠循环 如果您想通过管道传输traptest的输出,例如try,这甚至是可行的
{./traptest;echo>&2 exitcode$?;}| cat-n修改程序,使父进程忽略该信号,但父进程不会/立即想到一些想法,在不了解任何代码库的情况下,您可以确保所有子进程都具有与父进程相关的唯一名称,例如,一切都以foo_project_child_作为前缀,这样你就可以简单地使用pkill-f foo_project_child_来处理事情,否则,你是否反对使用像redis这样的数据存储,你可以查询并找出需要杀死哪些进程?如果可能的话,我不想对所有foo_project_等实例进行全局pkill,我希望这是独立的。我还没有调查过redis,我现在会的@Ed如何修改shell脚本使其不被终止,但其子进程将被终止?这是我的问题。@grasevski-Use trapthis不会杀死它的子进程。它在这里是什么?背景工作的孩子们?通常情况下,一份工作死后确实会杀死它的孩子。如果它没有这样做,可能是它以一种相反的方式对自己进行了守护或注册了信号处理程序。如果是这样的话,最好修改后台作业。你能做到吗?我同意你的观点,干净的解决办法是修改后台作业以终止其进程。我会尝试这样做,否则我会放弃,选择一个像kill 0这样的黑客解决方案。不幸的是,另一个程序是一个蹩脚的第三方脚本。我可能必须修复/重写它,因为似乎没有简单的方法来告诉组中的其他进程,例如从管道或周围的shell中告诉那些由该脚本生成的进程。如果有一种自包含的方法来简单地包装那个蹩脚的脚本,那么包装好的脚本将杀死这个蹩脚脚本启动的一切,但没有别的。问题是,如果我将我的脚本导入另一个程序,如head、tail等,那么这些脚本也将被删除,返回代码将为143。这使得从我的脚本中获取正确的返回代码变得很麻烦。在这种情况下,我认为您需要保存父进程的每个子进程的PID,以便可以单独杀死它们。
#!/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"
#!/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"