我有一个脚本在开始时运行后台进程,然后到最后需要停止后台进程及其子进程,然后执行其他任务等,然后在必要时返回错误代码。我该怎么做呢?我已经看到了几个如何杀死整个树的例子,包括父进程(例如kill 0
),但我希望主脚本继续运行并返回正确的错误代码。 E.g:
./some_process_with_child_processes &
./do_stuff
kill $! # doesnt kill child processes!
./do_other_stuff
exit 5
答案 0 :(得分:0)
您需要在
之后立即捕获$!
(子PID)
/some_process_with_child_processes &
pid=$!
./do_stuff
kill $pid
./do_other_stuff
答案 1 :(得分:0)
扩展Ed Heal的评论:
在父进程中,陷阱SIGTERM,例如
trap "echo received sigterm" SIGTERM
然后,当您想终止所有子进程时,在主脚本中执行
kill -s SIGTERM 0
父母也将收到SIGTERM,但这并不重要,因为它已被困信号。
您可能还发现在子进程中为EXIT设置陷阱很有用,这样他们就可以在收到SIGTERM时进行清理。
你可以发送子进程SIGKILL,但这有点残酷,并且子进程没有机会进行任何清理。
修改强>
以下是一些脚本,用于说明父脚本如何单独杀死其子级,而不是使用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"
如果你想管道traptest
的输出,这甚至可以工作,例如尝试
{ ./traptest; echo >&2 exitcode $?; } | cat -n