你如何杀死所有的子进程不杀死父母 [英] How do you kill all child processes without killing the parent

查看:145
本文介绍了你如何杀死所有的子进程不杀死父母的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有在开始运行后台进程的脚本,然后朝最终需要停止后台进程和它的孩子们,然后做一些其他任务等必要时再返回错误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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆