我有一个看起来像这样的脚本。调用方式为./myscript.sh start
#!/bin/bash
if [[ "$1" == "start" ]]; then
echo "Dev start script process ID: $$"
cd /my/path1
yarn dev &> /my/path/logs/log1.log &
echo "started process1 in background"
echo "Process ID: $!"
echo "Logging output at logs/log1.log"
sleep 2
cd /my/path2
yarn start:dev &> /my/path/logs/log2.log &
echo "started process2 in background"
echo "Process ID: $!"
echo "Logging output at logs/log2.log"
sleep 2
cd /my/path2
yarn dev &> /my/path/logs/log3.log &
echo "started process3 in background"
echo "Process ID: $!"
echo "Logging output at logs/log3.log"
elif [[ "$1" == "stop" ]]; then
killList=`ps | grep node | awk '{print $1}'`
if [[ $killList != "" ]]; then
echo $killList | xargs kill
echo "Processes killed: $killList"
else
echo "Nothing to stop"
fi
else
echo "Invalid argument"
fi
当我运行此脚本后运行时ps
,我可以看到一堆我认为已由命令启动的节点进程(超过 3 个)yarn dev
。我想运行./myscript.sh stop
并停止我之前运行 ./myscript.sh start 生成的所有节点进程
我怎样才能做到这一点?
答案1
您可以获得进程列表直接地由此产生bash
并发送给SIGTERM
他们:
pgrep -P $$ --signal SIGTERM
$$
是当前bash脚本的进程号。
根据子进程处理信号的方式,这可能会或不会杀死孙进程(等等,递归地)。
因此,另一种方法是列出从您开始的整个进程树bash
,然后杀死它们。
pstree -A -p $$ | grep -Eow "[0-9]+" | xargs kill
pstree
输出树(为人类格式化),grep
提取进程号,然后对它们执行您需要执行的操作,例如kill
为每个进程运行。
请注意,上面的行pstree
还将列出grep
和xargs
进程,因此您将收到No such process
来自 的两个警告kill
。不确定是否存在竞争条件,这只是概念证明。您可以对管道的右侧进行编码,以正确处理进程列表、过滤器等。