我想杀死整个进程树。使用通用脚本语言实现这一目标的最佳方法是什么?我在寻找一个简单的解决办法。
当前回答
下面是@zhigang的答案的一个变种,它没有AWK,只依赖于Bash的本地解析可能性:
function killtree {
kill -STOP "$1"
ps -e -o pid= -o ppid= | while read -r pid ppid
do
[[ $ppid = $1 ]] || continue
killtree "$pid" || true # Skip over failures
done
kill -CONT "$1"
kill -TERM "$1"
}
它在mac和Linux上都运行得很好。在您不能依赖于管理流程组的情况下——比如在编写测试必须在多个环境中构建的软件的脚本时——这种遍历树技术绝对是有用的。
其他回答
rkill命令从pslist包发送给定的信号(或SIGTERM默认)到指定的进程及其所有后代:
rkill [-SIG] pid/name...
修改后的志刚回答:
#!/usr/bin/env bash
set -eu
killtree() {
local pid
for pid; do
kill -stop $pid
local cpid
for cpid in $(pgrep -P $pid); do
killtree $cpid
done
kill $pid
kill -cont $pid
wait $pid 2>/dev/null || true
done
}
cpids() {
local pid=$1 options=${2:-} space=${3:-}
local cpid
for cpid in $(pgrep -P $pid); do
echo "$space$cpid"
if [[ "${options/a/}" != "$options" ]]; then
cpids $cpid "$options" "$space "
fi
done
}
while true; do sleep 1; done &
cpid=$!
for i in $(seq 1 2); do
cpids $$ a
sleep 1
done
killtree $cpid
echo ---
cpids $$ a
如果你知道传递父进程的pid,下面这个shell脚本应该可以工作:
for child in $(ps -o pid,ppid -ax | \
awk "{ if ( \$2 == $pid ) { print \$1 }}")
do
echo "Killing child process $child because ppid = $pid"
kill $child
done
要递归地杀死进程树,请使用killtree():
#!/bin/bash
killtree() {
local _pid=$1
local _sig=${2:--TERM}
kill -stop ${_pid} # needed to stop quickly forking parent from producing children between child killing and parent killing
for _child in $(ps -o pid --no-headers --ppid ${_pid}); do
killtree ${_child} ${_sig}
done
kill -${_sig} ${_pid}
}
if [ $# -eq 0 -o $# -gt 2 ]; then
echo "Usage: $(basename $0) <pid> [signal]"
exit 1
fi
killtree $@
我不能评论(没有足够的声誉),所以我被迫添加一个新的答案,即使这不是一个真正的答案。
@olibre在2月28日给出了一个非常好的、彻底的回答,但有一个小问题。ps opgid= $PID的输出将包含小于5位的PID的前导空格,因为ps正在对列进行对齐(将数字右对齐)。在整个命令行中,这会导致一个负号,后面跟着空格(s),然后是组PID。简单的解决方案是通过管道将ps传送到tr以删除空格:
kill -- -$( ps opgid= $PID | tr -d ' ' )
推荐文章
- 在Bash中检查变量是否存在于列表中
- 查看PS命令的全部输出
- 确保一次只运行一个shell脚本实例的快速方法
- Linux命令将域名转换为IP
- 如何从命令行在windows中找到mysql数据目录
- 如何在Makefile中设置子进程的环境变量
- 如何让“wc -l”打印没有文件名的行数?
- 有效地测试Linux上的端口是否打开?
- 如何从另一个文件A中删除文件B中出现的行?
- 对以制表符分隔的文件进行排序
- Shell脚本删除超过n天的目录
- 使用sudo时未找到命令
- 当有命令行参数时,如何使用GDB分析程序的核心转储文件?
- 如何检查shell脚本中是否存在命令?
- 如何使用查找命令从列表中查找所有具有扩展名的文件?