如何在不知道子进程名称的情况下跟踪并终止通过运行脚本生成的所有进程?

问题描述 投票:0回答:1

我有一个 Bash 包装器脚本,它启动一个复杂的建模脚本,该脚本又启动其自己的多个子进程和脚本。我想弄清楚如何跟踪一次运行建模脚本所产生的所有进程,以便在满足某些条件时杀死所有进程。

例如,我的包装脚本名为

pipeline_runner.sh
执行以下操作:

#!/bin/bash

# Some set up of the script ...

./monitor_job.sh ... arguments TBD ... &

script_path="path/to/bash/script"

chmod u+x "$script_path"
"$script_path"

# ...

每次运行

pipeline_runner.sh
都会在后台启动一个
monitor_job.sh
实例,以监视由该运行的
path/to/bash/script
启动的
pipeline_runner.sh
的特定运行。当满足
monitor_job.sh
中定义的任意条件时,它应该能够终止
path/to/bash/script
的特定运行,以及由它直接或间接启动的所有进程。

运行

path/to/bash/script
启动的多个其他进程很多且可变,所以我试图弄清楚如何捕获通过将其运行到某种组或列表中而产生的每个脚本,并能够将它们全部杀死当需要时。仅杀死最初的
$script_path
进程是不够的,因为该脚本的所有子进程都将存活下来。

重要的次要目标是:

  • 使其动态化,以便它不依赖于

    $script_path
    指定的脚本。这意味着我不能只是硬编码特定的命令名称来查找。

  • 按照描述在单独的脚本 (

    monitor_job.sh
    ) 中执行监控,而不是直接在
    pipeline_runner.sh
    中执行监控。

如何跟踪建模脚本启动的所有进程,以便能够在需要时将它们全部杀死?

linux bash shell
1个回答
0
投票

kill -- -$$
将终止整个进程组。

例如,在下面的脚本中,我们生成 2 个子进程,

sleep 15
sleep 30
,然后我们可以运行各种其他任务(在本例中为
sleep 5
),并且由于我们满足退出标准,我们可以杀死全流程组。

#!/bin/sh
echo "Parent pid $$"
sleep 15 &
echo "child 1 pid $!"

sleep 30 &
echo "child 2 pid $!"

sleep 5
echo "criteria met"
kill -- -$$

如果我们用

bash test.sh ;  ps -ef | grep sleep
运行它,我们会得到:

$ bash test.sh ;  ps -ef | grep sleep
Parent pid 87546
child 1 pid 87547
child 2 pid 87548
criteria met
Terminated: 15
  501 87595   789   0  2:08PM ttys007    0:00.00 grep sleep

因此我们观察到子进程也已被终止。

这种方法的问题是,如果在执行后直接输入 ctrl+c,我们会得到:

$ bash test.sh ;  ps -ef | grep sleep
Parent pid 88352
child 1 pid 88353
child 2 pid 88354
^C
  501 88353     1   0  2:10PM ttys007    0:00.00 sleep 15
  501 88354     1   0  2:10PM ttys007    0:00.00 sleep 30
  501 88391   789   0  2:10PM ttys007    0:00.00 grep sleep

这意味着各个子进程将继续作为孤儿进程运行(由 init 进程采用)。

为了解决这个问题,我们可以使用

trap
,并将脚本更改为:

#!/bin/sh

trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT

echo "Parent pid $$"

sleep 15 &
echo "child 1 pid $!"

sleep 30 &
echo "child 2 pid $!"

sleep 5
echo "criteria met"
exit 0

正常执行将保持不变,因为

exit 0
将被陷阱捕获,而
kill -- -$$
将像以前一样执行。

现在,如果我们运行脚本并在执行后直接输入 ctrl+c,这次我们会得到:

Parent pid 91578
child 1 pid 91579
child 2 pid 91580
^CTerminated: 15
  501 91590   789   0  2:18PM ttys007    0:00.00 grep sleep

我们看到子进程也被杀死了。

© www.soinside.com 2019 - 2024. All rights reserved.