实时打印过程输出


printing process output in realtime

我在Windows 7 x64系统上使用PHP 5.3.4和Apache 2.2.17。我想让我的PHP页面将system调用的结果实时输出到用户的浏览器。为此,我在php.ini中配置了output_buffering=Off,并创建了以下代码:

<?php
ob_implicit_flush(true);
ob_end_flush();
system('ping -n 10 www.google.com');
?>

ping的结果是实时打印的,但我也会在页面顶部收到一个PHP诊断错误和调用堆栈,上面写着:

Notice: ob_end_flush() [ref.outcontrol]: failed to delete and flush buffer. No buffer to delete or flush in index.php on line 3

我需要做些什么来纠正或抑制此错误?

更新如果我将ob_end_flush()更改为$a = 1/0;,我会得到类似的错误,并且在所有浏览器中输出都是实时的。是不是因为打印异常的方式导致了这种情况的发生?

某些web浏览器在某些条件下,在开始渲染页面之前缓冲前x个字节。

尝试先输出大量空白

我有一个有效的解决方案,但它是非性能的,而且很恶心。我抛出了一个异常,但隐藏了异常对话框。

<?php
    ob_implicit_flush(true);
    // Something about the way exceptions are thrown causes Firefox and Chrome 
    // to be able to display the results of the system call in real-time rather
    // than having to wait for the call to complete. So, I just hide the 
    // exception message. IE9 works with or without this.
    echo "<div style='"display:none'">";
    $a = 1/0;
    echo "</div>";
    echo "<pre>";
    system('ping -n 5 www.google.com');
    echo "</pre>";
?>

为了自动滚动到页面底部,我添加了一些javascript:

<html><head>
<script language="javascript">
var int = self.setInterval("window.scrollBy(0,1000);", 200);
</script>
</head>
<body>
<?php
    // insert above php code here
    // stop scrolling when the execution finishes
    echo '<script language="javascript">int = window.clearInterval(int);</script>';
?>
</body>
</html>

编辑

@Chris的回答显示了一个更好的解决方案。

echo '<div style="display:none">';
for ($a = 0; $a < 768; $a++)
    echo ' ';
echo '</div>';

只需添加此项即可刷新缓冲区:

    if (eregi("chrome",$_SERVER['HTTP_USER_AGENT'])) {
       echo "<div style='"display:none'">";
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";    
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";    
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
          echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
       echo "</div>";
    }

它必须在循环内部。或者在需要实时显示的两个输出之间。

这里有一个简写技巧:

添加以下内容:

if (eregi("chrome",$_SERVER['HTTP_USER_AGENT'])) {
   echo "<div style='"display:none'"></div>";                    
}

ob_end_flush()刷新php输出缓冲区,并需要使用ob_start()创建活动输出缓冲区。

我认为您只想调用flush()将数据发送到客户端。

<?php
ob_implicit_flush(true);
flush();
system('ping -n 10 www.google.com');
?>

在代码中,错误很容易解释。

您在第3行调用ob_end_flush(),但是(就像错误所说的),没有要刷新的输出。本质上,第3行是无用的,因为没有发送任何输出,所以删除该行将修复错误。如果将其合并到一个较大的文件中,则可能需要保留ob_end_flush(),因为可能已经捕获了一些输出。

编辑:既然你需要冲洗它,要么:

a: 将ob_start();添加到文件顶部。

b: 用flush(); 代替ob_end_flush();

第二版:由于第一个似乎不起作用,这是我能提供的最好的:如何实时(在脚本完成之前)回声输出?