当我中断 bash 脚本时尝试关闭所有子进程

agh*_*ith 9 bash interrupt child-process bash-trap

我编写了一个 bash 脚本来对我的系统进行一些测试。测试在后台并行运行。测试可能需要很长时间,有时我可能希望中途中止测试。

如果我 Control+C 那么它会中止父脚本,但让各个子脚本继续运行。我希望这样我就可以按 Control+C 或其他方式退出,然后杀死在后台运行的所有子进程。如果我直接从终端运行后台作业,我有一些代码可以完成这项工作,但它在我的脚本中不起作用。

我有一个最小的工作示例。

我尝试过将 trap 与 pgrep -P $$ 结合使用。

#!/bin/bash

trap 'kill -n 2 $(pgrep -P $$)' 2
sleep 10 &
wait
Run Code Online (Sandbox Code Playgroud)

我希望点击 control+c (SIGINT) 会杀死脚本启动的所有内容,但它实际上说:

./breakTest.sh: line 1: kill: (3220) - No such process
Run Code Online (Sandbox Code Playgroud)

这个数字发生了变化,但似乎不适用于任何正在运行的进程,所以我不知道它来自哪里。

我想如果 trap 命令的内容在 trap 命令发生的地方被评估,那么它可能会解释结果。3220 pid 可能用于 pgrep 本身。

我希望能在这里得到一些见解

谢谢

agh*_*ith 8

我找到了使用 pkill 的解决方案。该示例还涉及许多子进程。

#!/bin/bash
trap 'pkill -P $$' SIGINT SIGTERM
for i in {1..10}; do
   sleep 10 &
done
wait
Run Code Online (Sandbox Code Playgroud)

这似乎优雅地杀死了所有子进程。尽管除了发送正确的信号之外,我并没有正确理解原始代码的问题是什么。

  • 另外,我发现我需要在陷阱中同时使用 SIGTERM 和 SIGINT 来最优雅地终止作业。SIGINT 本身会发出有关正在被终止的作业的警告消息。谢谢 (2认同)
  • 最好在杀死子进程后显式退出。否则,如果您有一个循环在原始进程退出后生成一批新进程,则在陷阱杀死旧进程后您仍然会获得新进程(并继续执行循环)。即“陷阱”pkill -P $$; 退出'SIGINT SIGTERM` (2认同)

Joh*_*abb 0

您可以尝试如下操作:

pkill -TERM -P <your_parent_id_here>
Run Code Online (Sandbox Code Playgroud)