Racing进程组ID,如何杀掉该组?

Racing进程组ID,如何杀掉该组?

我正在学习流程组,这对我来说是一个新事物。 (我尝试遵循这个答案,除其他外:为什么 SIGINT 发送到其父进程时没有传播到子进程?)。我尝试但无法终止进程组,因为它的 ID 似乎正在消失。

$ sleep 1000 &
[1] 6468
$ ps ax -O tpgid | grep sleep
 6468  6511 S pts/4    00:00:00 sleep 1000
 6512  6511 S pts/4    00:00:00 grep --color=auto sleep
$ kill -9 -6511
bash: kill: (-6511) - No such process
$ ps ax -O tpgid | grep sleep
 6468  6515 S pts/4    00:00:00 sleep 1000
 6516  6515 S pts/4    00:00:00 grep --color=auto sleep
$ ps ax -O tpgid | grep sleep
 6468  6517 S pts/4    00:00:00 sleep 1000
 6518  6517 S pts/4    00:00:00 grep --color=auto sleep

为什么会这样,怎样才能抓住并杀死它呢?我得到了什么以及做错了什么?

GNU bash,版本 4.3.42(1)-release (x86_64-pc-linux-gnu)

答案1

这是因为您没有打印进程组 ID (PGID),而是打印“控制 tty 进程组 ID”tpgid。正如中所解释的man ps

   tpgid       TPGID     ID of the foreground process group on the tty
                         (terminal) that the process is connected to, or
                         -1 if the process is not connected to a tty.

因此,您看到的是前台进程的 PID,在您的情况下,它是程序ps

$ sleep 1000 &
[1] 6745
$ ps ax -O tpgid | grep -E 'sleep|ps a'
 6745  7136 S pts/1    00:00:00 sleep 1000
 7136  7136 R pts/1    00:00:00 ps ax -O tpgid
 7137  7136 S pts/1    00:00:00 grep --color -E sleep|ps a

如上所示,打印的 tpgid 值是进程的 PID ps。您正在寻找的是pgid,而不是tpgid

   pgid        PGID      process group ID or, equivalently, the process ID
                         of the process group leader.  (alias pgrp).


$ ps ax -O pgid | grep -E 'sleep|ps a'
 8414  8414 S pts/1    00:00:00 sleep 1000
 8656  8656 R pts/1    00:00:00 ps ax -O pgid
 8657  8656 S pts/1    00:00:00 grep --color -E sleep|ps a

当然,由于您实际上并未运行任何进程组(例如,当一个脚本调用其他脚本时会发生这种情况),因此 PGIDsleep与其 PID 相同。不过,如果你愿意的话,你实际上可以这样杀死它:

$ kill -9 -8414
$ ps ax -O pgid | grep -E 'sleep|ps a'
10065 10065 R pts/1    00:00:00 ps ax -O pgid
10066 10065 S pts/1    00:00:00 grep --color -E sleep|ps a
[1]+  Killed                  sleep 1000

一个更具信息性的示例是运行如下脚本:

#!/bin/bash

sleep 1000 &
sleep 1000 &
sleep 1000 &

sleep 1000

如果我将其另存为foo.sh并运行它,则各种sleep命令都将具有相同的 PGID:

$ foo.sh &
[1] 13555
$ ps ax -O pgid | grep -P '[s]leep|[f]oo.sh'
13555 13555 S pts/1    00:00:00 /bin/bash /home/terdon/scripts/foo.sh
13556 13555 S pts/1    00:00:00 sleep 1000
13557 13555 S pts/1    00:00:00 sleep 1000
13558 13555 S pts/1    00:00:00 sleep 1000
13559 13555 S pts/1    00:00:00 sleep 1000

因此,每个子进程都位于父进程的进程组中foo.sh。如果我们现在杀死进程组,所有进程都将退出:

$ kill -9 -13555
$ ps ax -O pgid | grep -P '[s]leep|[f]oo.sh'
[1]+  Killed                  foo.sh

相关内容