proc_terminate

(PHP 5, PHP 7, PHP 8)

proc_terminate终止由 proc_open 打开的进程

描述

proc_terminate(资源 $process, 整数 $signal = 15): 布尔值

process(使用 proc_open() 创建)发出终止信号。 proc_terminate() 会立即返回,不会等待进程终止。

proc_terminate() 允许您终止进程并继续执行其他任务。可以使用 proc_get_status() 函数轮询进程(查看进程是否已停止)。

参数

process

将要关闭的 proc_open() 资源

signal

此可选参数仅在 POSIX 操作系统上有效;您可以使用 kill(2) 系统调用指定要发送给进程的信号。默认值为 SIGTERM

返回值

返回运行的进程的终止状态。

参见

  • proc_open() - 执行命令并为输入/输出打开文件指针
  • proc_close() - 关闭由 proc_open 打开的进程并返回该进程的退出代码
  • proc_get_status() - 获取由 proc_open 打开的进程的信息

添加注释

用户贡献的注释 4 个注释

csh dot spam at me dot com
10 年前
/bin/sh -c CMD 将分叉 sh,然后执行 CMD。
/bin/sh -c exec CMD 不会分叉,只会执行 CMD。

因此,您可以通过在命令前加 "exec bla bla bla" 来消除这种 hack。
jerhee at ucsd dot edu
16 年前
http://bugs.php.net/bug.php?id=39992, 中所述,proc_terminate() 会让子进程的子进程继续运行。在我的应用程序中,这些子进程通常有无限循环,因此我需要一种可靠的方法来杀死使用 proc_open() 创建的进程。当我调用 proc_terminate() 时,/bin/sh 进程会被杀死,但具有无限循环的子进程会继续运行。

在 proc_terminate() 被修复之前,我不建议使用它。相反,我的解决方案是
1) 调用 proc_get_status() 获取要杀死的进程的父进程 ID (ppid)。
2) 使用 ps 获取所有具有该 ppid 作为父进程 ID 的进程 ID。
3) 使用 posix_kill() 向这些子进程 ID 中的每一个发送 SIGKILL (9) 信号。
4) 对进程资源调用 proc_close()。

<?php
$descriptorspec
= array(
0 => array('pipe', 'r'), // stdin 是一个管道,子进程将从中读取
1 => array('pipe', 'w'), // stdout 是一个管道,子进程将写入其中
2 => array('pipe', 'w') // stderr 是一个管道,子进程将写入其中
);
$process = proc_open('bad_program', $descriptorspec, $pipes);
if(!
is_resource($process)) {
throw new
Exception('bad_program 无法启动。');
}
// 向程序传递一些输入
fwrite($pipes[0], $lots_of_data);
// 关闭 stdin。通过关闭 stdin,程序应在完成输入处理后退出
//
fclose($pipes[0]);

// 做一些其他事情 ... 进程可能仍然在运行
// 如果我们立即检查它

$status = proc_get_status($process);
if(
$status['running'] == true) { // 进程运行时间过长,将其杀死
// 关闭所有仍然打开的管道
fclose($pipes[1]); // stdout
fclose($pipes[2]); // stderr
// 获取要杀死的进程的父进程 ID
$ppid = $status['pid'];
// 使用 ps 获取此进程的所有子进程,并将其杀死
$pids = preg_split('/\s+/', `ps -o pid --no-heading --ppid $ppid`);
foreach(
$pids as $pid) {
if(
is_numeric($pid)) {
echo
"杀死 $pid\n";
posix_kill($pid, 9); // 9 是 SIGKILL 信号
}
}

proc_close($process);
}

?>
v dot denegin at yahoo dot com
10 年前
在 Windows 平台上,proc_terminate() 不会杀死不处理杀死信号的子进程。即使您调用 xxx.exe 并调用 proc_terminate(),进程也会保持活动状态。

解决方案是不要调用 proc_terminate(),而是调用用户定义的 kill() 函数(已经针对 win/unix 进行了优化)
之后需要关闭所有管道并执行 proc_close()。

function kill($pid){
return stripos(php_uname('s'), 'win')>-1 ? exec("taskkill /F /T /PID $pid") : exec("kill -9 $pid");
}

function killall($pids) {
$os=stripos(php_uname('s'), 'win')>-1;
($_=implode($os?' /PID ':' ',$pids)) or ($_=$pids);
return preg_match('/success|close/', $os ? exec("taskkill /F /T /PID $_") : exec("kill -9 $_"));
}

示例

$pstatus = proc_get_status($resource);
$PID = $pstatus['pid'];

// 其他命令

kill($PID); // 代替 proc_terminate($resource);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($resource);
smcbride at msn dot com
3 年前
只是一个小的说明,这样人们就不用去别的地方查找了

要获取进程列表或按名称查找进程,请使用
$proclist = shell_exec('ps -elF') 用于 linux
$proclist = shell_exec('tasklist') 用于 windows

之后,您可以使用 php 的正常解析函数来获取进程 ID
To Top