使用PHP中的实时输出运行进程

Mak*_*Vi. 67 php linux apache real-time process

我正在尝试在网页上运行一个将实时返回其输出的进程.例如,如果我运行'ping'进程,它应该在每次返回一个新行时更新我的​​页面(现在,当我使用exec(命令,输出)时,我被迫使用-c选项并等待进程完成以查看在我的网页上输出).有可能在PHP中这样做吗?

我也想知道当有人离开页面时,杀死这种过程的正确方法是什么.在"ping"过程中,我仍然可以看到系统监视器中运行的进程(有意义).

ega*_*fni 91

这对我有用:

$cmd = "ping 127.0.0.1";

$descriptorspec = array(
   0 => array("pipe", "r"),   // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),   // stdout is a pipe that the child will write to
   2 => array("pipe", "w")    // stderr is a pipe that the child will write to
);
flush();
$process = proc_open($cmd, $descriptorspec, $pipes, realpath('./'), array());
echo "<pre>";
if (is_resource($process)) {
    while ($s = fgets($pipes[1])) {
        print $s;
        flush();
    }
}
echo "</pre>";
Run Code Online (Sandbox Code Playgroud)

  • +1对我有用,但前提是我在开头添加`ob_implicit_flush(true); ob_end_flush();` (18认同)
  • 但是......最后应该使用proc_close(). (12认同)
  • 将其与罗布的答案结合起来,你就明白了。 (2认同)

小智 37

这是显示shell命令的实时输出的好方法:

<?php
header("Content-type: text/plain");

// tell php to automatically flush after every output
// including lines of output produced by shell commands
disable_ob();

$command = 'rsync -avz /your/directory1 /your/directory2';
system($command);
Run Code Online (Sandbox Code Playgroud)

您将需要此功能来防止输出缓冲:

function disable_ob() {
    // Turn off output buffering
    ini_set('output_buffering', 'off');
    // Turn off PHP output compression
    ini_set('zlib.output_compression', false);
    // Implicitly flush the buffer(s)
    ini_set('implicit_flush', true);
    ob_implicit_flush(true);
    // Clear, and turn off output buffering
    while (ob_get_level() > 0) {
        // Get the curent level
        $level = ob_get_level();
        // End the buffering
        ob_end_clean();
        // If the current level has not changed, abort
        if (ob_get_level() == $level) break;
    }
    // Disable apache output buffering/compression
    if (function_exists('apache_setenv')) {
        apache_setenv('no-gzip', '1');
        apache_setenv('dont-vary', '1');
    }
}
Run Code Online (Sandbox Code Playgroud)

它不会每次我都试了一下,虽然服务器上工作,我希望我能提供在你的PHP配置要寻找什么意见,以决定你是否应该拉你的头发,试图让这种行为的工作在你的服务器上!其他人都知道吗?

这是普通PHP中的一个虚拟示例:

<?php
header("Content-type: text/plain");

disable_ob();

for($i=0;$i<10;$i++) 
{
    echo $i . "\n";
    usleep(300000);
}
Run Code Online (Sandbox Code Playgroud)

我希望这能帮助那些在谷歌上搜索的人.


rom*_*nsh 7

这里描述了使用现代HTML5服务器端事件解决这个老问题的更好方法:

http://www.w3schools.com/html/html5_serversentevents.asp


例:

http://sink.agiletoolkit.org/realtime/console

代码:https://github.com/atk4/sink/blob/master/admin/page/realtime/console.php#L40

(作为Agile Toolkit框架中的模块实现)


mpe*_*pen 6

对于命令行用法:

function execute($cmd) {
    $proc = proc_open($cmd, [['pipe','r'],['pipe','w'],['pipe','w']], $pipes);
    while(($line = fgets($pipes[1])) !== false) {
        fwrite(STDOUT,$line);
    }
    while(($line = fgets($pipes[2])) !== false) {
        fwrite(STDERR,$line);
    }
    fclose($pipes[0]);
    fclose($pipes[1]);
    fclose($pipes[2]);
    return proc_close($proc);
}
Run Code Online (Sandbox Code Playgroud)

如果您尝试运行文件,则可能需要首先授予其执行权限:

chmod('/path/to/script',0755);
Run Code Online (Sandbox Code Playgroud)


Pix*_*xsa 6

检查所有答案,没有任何效果...

在这里找到解决方案

它在Windows上有效(我认为此答案对在那边搜索的用户很有帮助)

<?php
$a = popen('ping www.google.com', 'r'); 

while($b = fgets($a, 2048)) { 
echo $b."<br>\n"; 
ob_flush();flush(); 
} 
pclose($a); 

?>
Run Code Online (Sandbox Code Playgroud)


ram*_*ous 5

尝试一下(在Windows计算机+ Wamp服务器上测试)

        header('Content-Encoding: none;');

        set_time_limit(0);

        $handle = popen("<<< Your Shell Command >>>", "r");

        if (ob_get_level() == 0) 
            ob_start();

        while(!feof($handle)) {

            $buffer = fgets($handle);
            $buffer = trim(htmlspecialchars($buffer));

            echo $buffer . "<br />";
            echo str_pad('', 4096);    

            ob_flush();
            flush();
            sleep(1);
        }

        pclose($handle);
        ob_end_flush();
Run Code Online (Sandbox Code Playgroud)

  • 这个答案是错误的。问题是如何实时获取页面输出。使用ob_start()可以做相反的事情:将所有输出写入内部服务器缓冲区,而不是立即将其发送到浏览器! (2认同)

Nux*_*Nux 5

我在Windows上尝试了各种PHP执行命令,发现它们之间有很大的不同。

  • 不要为工作流:shell_execexecpassthru
  • 种类:proc_openpopen--“种类”,因为您无法将参数传递给命令(即,不会与一起使用my.exe --something,将与一起使用_my_something.bat)。

最好的(最简单的)方法是:

  1. 您必须确保您的exe正在刷新命令(请参阅printf刷新问题)。没有此操作,无论您做什么,您很可能会收到大约4096字节的文本批次。
  2. 如果可以,请使用header('Content-Type: text/event-stream');(而不是header('Content-Type: text/plain; charset=...');)。但是,这并非在所有浏览器/客户端中都适用!流媒体将在没有此功能的情况下工作,但是浏览器至少会缓冲第一行。
  3. 您可能还想禁用缓存header('Cache-Control: no-cache');
  4. 关闭输出缓冲(在php.ini中或使用ini_set('output_buffering', 'off');)。这可能也必须在您前面使用的Apache / Nginx /任何服务器中完成。
  5. 压缩转向(在php.ini中或使用ini_set('zlib.output_compression', false);)。这可能也必须在您前面使用的Apache / Nginx /任何服务器中完成。

因此,在您的C ++程序中,您可以执行以下操作(同样,有关其他解决方案,请参见printf刷新问题):

Logger::log(...) {
  printf (text);
  fflush(stdout);
}
Run Code Online (Sandbox Code Playgroud)

在PHP中,您可以执行以下操作:

function setupStreaming() {
    // Turn off output buffering
    ini_set('output_buffering', 'off');
    // Turn off PHP output compression
    ini_set('zlib.output_compression', false);
    // Disable Apache output buffering/compression
    if (function_exists('apache_setenv')) {
        apache_setenv('no-gzip', '1');
        apache_setenv('dont-vary', '1');
    }
}
function runStreamingCommand($cmd){
    echo "\nrunning $cmd\n";
    system($cmd);
}
...

setupStreaming();
runStreamingCommand($cmd);
Run Code Online (Sandbox Code Playgroud)