Contents

杀死进程组的所有成员

1. 概述

Linux 系统管理中的一个常见场景是进程管理。虽然大多数进程很容易停止和管理,但在某些情况下,同一组中的大量进程可能需要停止。

在本教程中,我们将了解使用流程组进行流程管理。另外,如何杀死属于进程组的所有进程。

2. 进程组

Linux 中的进程组,顾名思义,是 Linux 将进程组合在一起的一种方式。它们是共享相同 PGID(进程组 ID)的相关进程的集合。

一个常见的误解是杀死父进程也会杀死子进程。然而,杀死父进程可以让子进程独立存在。我们将看到如何用进程组 id杀死一个进程来确保所有相关进程都停止。

每个进程组都有一个组长,其进程 id 与组内所有进程的 PGID 相同

3. 设置分组进程列表

我们假设有一个应用程序进程的层次结构正在运行的场景。因此,我们将创建三个相互调用的脚本,并创建一组属于同一组的进程。

让我们继续创建一个名为grandparent.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.shchildren.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

现在,让我们运行最顶层的脚本,它将使用以下命令创建其他进程:

./grandparent.sh

4. 使用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]

5. 过滤进程列表输出

根据系统中运行的进程数量,需要过滤输出。让我们使用一些工具来帮助我们找到要停止的进程的 Process Groud Id。

根据我们在第 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 用作所有其他进程的 PGID。

6. 使用 PGID 杀死进程

让我们使用kill 命令使用以下格式向指定的进程组发送终止信号:

kill -- -$PGID

双破折号“- -”用于默认的SIGTERM 信号。如第 5 节所示,我们试图杀死的进程组的 PGID 是 6389。知道了这一点,我们可以使用 kill 命令杀死这个组:

kill -- -6389

我们还可以使用我们通常在进程中使用的任何信号。例如,让我们使用SIGKILL -9杀死进程组:

kill -9 -6389

此外,可以将SIGQUIT 信号发送到进程组以复制终端退出信号。

kill -SIGQUIT -6389