杀死进程组的所有成员
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.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
现在,让我们运行最顶层的脚本,它将使用以下命令创建其他进程:
./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