9

我一直使用:

$pid = exec("/usr/local/bin/php file.php $args > /dev/null & echo \$!");

但我正在使用 XP 虚拟机开发 Web 应用程序,但我不知道如何在 windows 中获取 pid。

我在cmd上试过这个:

C:\\wamp\\bin\\php\\php5.2.9-2\\php.exe "file.php args" > NUL & echo $!

它会执行文件,但输出是“$!”

如何将 pid 放入 var $pid 中?(使用 php)

4

4 回答 4

9

我正在使用Pstools,它允许您在后台创建一个进程并捕获它的 pid:

// use psexec to start in background, pipe stderr to stdout to capture pid
exec("psexec -d $command 2>&1", $output);
// capture pid on the 6th line
preg_match('/ID (\d+)/', $output[5], $matches);
$pid = $matches[1];

这有点hacky,但它完成了工作

于 2011-07-12T17:32:37.527 回答
1

多亏了谷歌,我才来到这里,并决定这篇已有十年历史的帖子需要更多信息,基于如何在 PHP 中调用/启动进程并使用进程 ID 杀死它......

想象一下,你想执行一个命令(这个例子使用 ffmpeg 将 windows 系统上的文件流式传输到 rtmp 服务器)。你可以命令这样的事情:

ffmpeg -re -i D:\wicked_video.mkv -c:v libx264 -preset veryfast -b:v 200k -maxrate 400k -bufsize 6000k -pix_fmt yuv420p -g 50 -c:a aac -b:a 160k -ac 2 -ar 44100 -f flv rtmp://<IP_OF_RMTP_SERVER>/superawesomestreamkey > d:\demo.txt 2> d:\demoerr.txt

第一部分在这里解释,该命令的最后一部分输出到具有该名称的文件以用于记录目的:

> d:\demo.txt 2> d:\demoerr.txt

因此,让我们假设该命令有效。你测试了它。要使用 php 运行该命令,您可以使用 exec 执行它,但这需要时间(另一个主题,检查set_time_limit),它是 ffmpeg 通过 php 处理的视频。不是要走的路,但在这种情况下正在发生。

您可以在后台运行该命令,但该进程的 pid 是什么?我们出于某种原因想要杀死它,psexec 只给出一个用户运行的“进程 ID”。在这种情况下只有一个用户。我们希望同一个用户有多个进程。

这是一个在 php 中获取已运行进程的 pid 的示例:

// the command could be anything:
// $cmd = 'whoami';

// This is a f* one, The point is: exec is nasty.
// $cmd = 'shutdown -r -t 0'; // 

// but this is the ffmpeg example that outputs seperate files for sake
$cmd = 'ffmpeg -re -i D:\wicked_video.mkv -c:v libx264 -preset veryfast -b:v 200k -maxrate 400k -bufsize 6000k -pix_fmt yuv420p -g 50 -c:a aac -b:a 160k -ac 2 -ar 44100 -f flv rtmp://10.237.1.8/show/streamkey1 > d:\demo.txt 2> d:\demoerr.txt';

// we assume the os is windows, pipe read and write
$descriptorspec = [  
    0 => ["pipe", "r"],  
    1 => ["pipe", "w"],  
];

// start task in background, when its a recource, you can get Parent process id
if ( $prog = is_resource( proc_open("start /b " . $cmd, $descriptorspec, $pipes ) ) )  
{  
    // Get Parent process Id  
    $ppid = proc_get_status($prog);  

    // this is the 'child' pid
    $pid = $ppid['pid'];

    // use wmic to get the PID
    $output = array_filter( explode(" ", shell_exec("wmic process get parentprocessid,processid | find \"$pid\"" ) ) );  
    array_pop($output);   
    
    // if pid exitst this will not be empty
    $pid = end($output);  

    // outputs the PID of the process 
    echo $pid;  
}  

上面的代码应该回显“inBackground”运行进程的 pid。

请注意,如果 pid 仍在运行,您需要保存 pid 以便稍后将其杀死。

现在你可以这样做来杀死进程:(想象 pid 是 1234)

//'F' to Force kill a process  
exec("taskkill /pid 1234 /F"); 

这是我在stackoverflow上的第一篇文章,我希望这会对某人有所帮助。度过一个美好而不孤单的圣诞节♪♪

于 2020-12-25T02:24:21.977 回答
0

您将不得不安装一个额外的扩展,但在Uniformserver 的 Wiki中找到了解决方案。

更新

经过一番搜索,您可能会tasklist巧合地查看一下,您可能可以使用 PHPexec命令来获得您想要的东西。

于 2010-09-09T19:08:06.850 回答
0

这是 SeanDowney 答案的一个不那么“hacky”的版本。

PsExec 返回生成进程的 PID 作为其整数退出代码。所以你只需要这样:

<?php

    function spawn($script)
    {
      @exec('psexec -accepteula -d php.exe ' . $script . ' 2>&1', $output, $pid);
      return $pid;
    } // spawn

    echo spawn('phpinfo.php');

?>

-accepteula 参数仅在您第一次运行 PsExec 时才需要,但如果您正在分发您的程序,每个用户都将是第一次运行它,并且在每次后续执行时都保留它并没有什么坏处。

PSTools 是一种快速简便的安装方式(只需将 PSTools 解压缩到某处并将其文件夹添加到您的路径中),因此没有充分的理由不使用此方法。

于 2019-01-28T17:46:52.800 回答