PHP 调用时无法终止进程组

PHP 调用时无法终止进程组

我有一个生成两个僵尸的脚本。我可以通过 杀死该组kill -- -<parent-pid>,但是当由 PHP 解释器调用时,这将不起作用,尽管手动杀死每个进程会起作用。

脚本是

#!/bin/bash
sleep 1d&
sleep 1d

PHP 文件只是调用它:

<?php
exec("./spawn")
?>

直接从外壳:

$ ./spawn&
[1] 19871    
$ pstree -p 19871
spawn(19871)─┬─sleep(19872)
             └─sleep(19873)    
$ kill -- -19871    
$ pstree -p 19871
[1]+  Terminated                 ./spawn

...并通过 PHP:

$ php -f zomby.php &
[1] 19935    
$ pstree -p 19935
php(19935)───sh(19936)───spawn(19937)─┬─sleep(19938)
                                      └─sleep(19939)
$ kill -- -19937
bash: kill: (-19937) - No matching process found
$ kill -- -19936
bash: kill: (-19936) - No matching process found
$ kill 19939 19938 19937     
$ Terminated    
[1]+  Fertig                  php -f zomby.php

只有杀死 PHP 父进程才有效:

$ php -f zomby.php &
[1] 20021

$ pstree -p 20021
php(20021)───sh(20022)───spawn(20023)─┬─sleep(20024)
                                      └─sleep(20025)
$ kill -- -20021

$ pstree -p 20021
[1]+  Terminated                 php -f zomby.php

对此有什么想法吗?

答案1

kill当给定的 PID < -1 时,该命令将其视为进程组 ID (PGID),而不是进程 ID。这记录在info kill

 ‘PID < -1’
      The process group whose identifier is −PID.

如果我们再次以你的例子为例:

$ pstree -p 19935
php(19935)───sh(19936)───spawn(19937)─┬─sleep(19938)
                                      └─sleep(19939)

PGID 是进程树最顶层父进程的 PID,在本例中为19935。然而,您试图杀死属于 ID 和 进程组的进程1993719936这两个进程实际上都不是进程组 ID。 PGID 是19935

您也许可以通过 更清楚地看到这一点ps。如果我在我的系统上运行相同的命令:

$ php -f ./zombie.php &
[2] 12882
$ ps  -o pid,ppid,pgid,command | grep -E '[P]GID|[1]2882'
  PID  PPID  PGID COMMAND
12882  1133 12882 php -f ./zombie.php
12883 12882 12882 /bin/bash ./spawn
12884 12883 12882 sleep 1d
12885 12883 12882 sleep 1d

在上面的示例中,该组的 PGID 是12882,所以如果我想杀死该组中的所有内容,我需要使用它。

当您直接从 shell 运行命令时,最顶层的父进程是 shell 脚本的 PID,因此您可以通过运行以下命令来终止其树中的所有进程kill -- -PID

$ ./spawn &
[3] 14213
terdon@tpad foo $ ps  -o pid,ppid,pgid,command | grep -E '[P]GID|[1]4213'
  PID  PPID  PGID COMMAND
14213  1133 14213 /bin/bash ./spawn
14214 14213 14213 sleep 1d
14215 14213 14213 sleep 1d

但那是因为 shell 脚本的 PID 是该组的 PGID。

相关内容