在 Linux 中杀死进程组的所有成员


概述

作为 Linux 系统管理员,处理进程是一项频繁的任务。通常,停止它们很容易,但在某些情况下——当同一组中存在大量进程时——可能需要采取其他步骤。

我们将更仔细地研究如何使用“组”的概念来管理进程。以及如何终止属于特定组的所有进程。

进程组

Linux 中的进程分组是一种 Linux 进程共享相同 PID(进程 ID)的方式。它们是一组相关的进程,共享相同的 PID。

杀死父进程并不一定意味着子进程也会被杀死。但是,如果我们杀死父进程,它们将不再运行。因此,我们将了解如何杀死特定的 pid(属于父进程的 pid)来停止其所有关联的 pid。

对于每个进程组,都有一个组长,其进程 ID(PGID)与组中的所有其他成员相同。

设置分组进程列表

我们假设一个正在运行的应用程序层次结构的情况。因此,我们将编写三个程序,它们将相互调用,创建许多子进程组。

让我们创建一个名为 parent.sh 的 shell 脚本,其内容如下:

#!/bin/bash
bash parent.sh &
bash parent.sh &
for i in {1..100}; do 
sleep 2; 
echo -n "This is the grandparent process $i"; 
done

现在让我们添加另一个名为 parent.sh 的脚本和一个名为 children.sh 的脚本。

#!/bin/bash
bash children.sh &
bash children.sh &
for i in {1..100}; do sleep 2; echo -n "This is the parent process $i"; 
done
#!/bin/bash
for i in {1..100}; do 
sleep 2; 
echo -n "This is a test in children process $i"; 
done

现在让我们运行最顶层的 shell 文件,它将使用以下命令启动其他进程:

./grandparent.sh

使用 ps 命令查找进程组

我们将使用 ps 获取当前正在运行的进程列表。

  • -e − 选择所有进程

  • -f − 默认情况下,ps 命令不显示完整格式的列表和 PGID 以及其他列作为选项。

  • -j − 以作业格式列出进程。

$ ps -efj
UID          PID    PPID    PGID     SID  C STIME TTY          TIME CMD
root           1       0       1       1  0 11:18 ?        00:00:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 18
root           2       0       0       0  0 11:18 ?        00:00:00 [kthreadd]
root           3       2       0       0  0 11:18 ?        00:00:00 [rcu_gp]
root           4       2       0       0  0 11:18 ?        00:00:00 [rcu_par_gp]
root           6       2       0       0  0 11:18 ?        00:00:00 [kworker/0:0H]
root           8       2       0       0  0 11:18 ?        00:00:00 [mm_percpu_wq]
root           9       2       0       0  0 11:18 ?        00:00:00 [ksoftirqd/0]
root          10       2       0       0  0 11:18 ?        00:00:00 [rcu_sched]

过滤进程列表输出

如果您的计算机中有多个进程正在运行,则可能需要过滤输出。我们将研究如何使用一些工具来帮助我们识别要终止的进程的进程组 ID(PGID)。

根据我们在第 3 节中构建的设置,应该有一组具有相同 PGID 的进程。

$ ps -efj | egrep "PGID|children|parent"

UID          PID    PPID    PGID     SID  C STIME TTY          TIME CMD
vagrant     6389    5377    6389    5377  0 12:49 pts/0    00:00:00 bash grandparent.sh
vagrant     6390    6389    6389    5377  0 12:49 pts/0    00:00:00 bash parent.sh
vagrant     6391    6389    6389    5377  0 12:49 pts/0    00:00:00 bash parent.sh
vagrant     6393    6390    6389    5377  0 12:49 pts/0    00:00:00 bash children.sh
vagrant     6394    6390    6389    5377  0 12:49 pts/0    00:00:00 bash children.sh
vagrant     6395    6391    6389    5377  0 12:49 pts/0    00:00:00 bash children.sh
vagrant     6397    6391    6389    5377  0 12:49 pts/0    00:00:00 bash children.sh
vagrant     6440    4570    6439    4570  0 12:49 pts/1    00:00:00 grep -E --color=auto PGID|children|parent

第 2 节讨论了第一个进程运行所有其他程序的 PID。然后将这些 PID 分配给所有其他正在运行的程序。

使用 PGID 杀死进程

我们将使用 kill 命令通过向进程发送 kill 信号来终止进程。以下是如何执行 kill 命令的示例:

kill -- -$PGID

两个破折号 (--) 表示默认的 SIGTERM 信号。根据图 5,我们要杀死的进程组的 PGID 为 6389。知道这一点,我们就知道可以使用“kill”命令杀死该组。

kill -- -6389

我们还可以使用通常与进程一起使用的信号。例如,如果我们想使用 SIGKILL –9 终止进程组,那么我们会输入:

kill -9 -6389

SIGQUIT 可用于向组内的进程发送终端退出信号。

kill -SIGQUIT -6389

结论

我们学习了如何使用“kill”命令终止属于同一进程组的进程。您可以通过发送 SIGTERM 或 SIG QUIT 信号来终止。使用此方法杀死正在运行的程序允许在大量程序不断运行的情况下。需要关闭程序。

更新于: 2023 年 1 月 3 日

1K+ 次查看

开启你的 职业生涯

通过完成课程获得认证

开始
广告