PHP:在Web浏览器中输出system / Shell_exec命令输出

时间:2013-11-27 16:56:41

标签: javascript php


我尝试使用shell_exec以类似的方式(同时)在终端中输出一个简单的ping命令。但它只在完成执行后显示,而我需要它在终端显示时显示,
我的代码是

<?php
$i= shell_exec("ping -c 4 google.com");
echo "<pre> $i <pre>";
?>

它正在等待一段时间并将整个东西倾倒在一个镜头上...... PHP可以识别每行的输出并将其显示在网页上

编辑
我也试过了

    <?php
    $proc = popen("ping -c 4 google.com", 'r');
    echo '<pre>';
    while (!feof($proc)) {
        echo fread($proc, 4096);
    }
    echo '</pre>';
    ?>

但我仍然得到相同的结果..

编辑
当我尝试在终端(php test.php)中执行此PHP代码时,它的工作方式与我们直接在服务器上执行ping时的方式相同。但在网页上它仍然是一样的。

7 个答案:

答案 0 :(得分:3)

嗯,来自网络浏览器的奇怪行为。我使用此代码:

<?php
ob_end_flush();
ini_set("output_buffering", "0");
ob_implicit_flush(true);

function pingtest()
{
    $proc = popen("ping -c 5 google.com", 'r');
    while (!feof($proc))
    {
        echo "[".date("i:s")."] ".fread($proc, 4096);
    }
}

?>
<!DOCTYPE html>
<html>
<body>
  <pre>
Immediate output: 
<?php
pingtest();
?>
  </pre>
</body>
</html>

在浏览器中,在收到所有字节后显示内容。 但是,内容实际上是按时交付的,请进行此测试:

wget -O - -q "http://localhost/ping.php"

您将看到响应由php&amp; apache2准时。

我在长期任务中使用这种执行一段时间,但使用更复杂的解决方案:

  • 接口
  • 的html文件
  • 运行长任务的php文件
  • 使用EventSource对象(在html5上提供)
  • 将html界面与php长执行连接

interface(test.html)

<!DOCTYPE html>
<html>
<head>
    <title>Simple EventSource example</title>
</head>
<body>
    <script type="text/javascript">
    function eventsourcetest() {
        var ta = document.getElementById('output');
        var source = new EventSource('test.php');
        source.addEventListener('message', function(e) {
            if (e.data !== '') {
               ta.value += e.data + '\n';
            }
        }, false);
        source.addEventListener('error', function(e) {
            source.close();
        }, false);
    }
    </script>
    <p>Output:<br/><textarea id="output" style="width: 80%; height: 25em;"></textarea></p>
    <p><button type="button" onclick="eventsourcetest();">ping google.com</button>
</html>

服务器端组件(test.php)

<?php
ob_end_flush();
ini_set("output_buffering", "0");
ob_implicit_flush(true);
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

function echoEvent($datatext) {
    echo "data: ".implode("\ndata: ", explode("\n", $datatext))."\n\n";
}

echoEvent("Start!");
$proc = popen("ping -c 5 google.com", 'r');
while (!feof($proc)) {
    echoEvent(fread($proc, 4096));
}
echoEvent("Finish!");

将两个文件放在网络服务器上的一个位置并输入test.html,我认为这是您从一开始就要查找的内容。

答案 1 :(得分:1)

使用输出缓冲和flush。您可能还想查看Symfony 2 process component

答案 2 :(得分:1)

它不是PHP的问题,或者说它是php和浏览器之间的共享问题。

在PHP中:确保输出缓冲已关闭,您可以在输出任何内容之前运行ob_end_clean()来执行此操作。

作为this SO post suggests,您必须填充输出为512字节的第一个字符串或通过http标头指定字符集编码。填充解决方案可能是解决此问题的最简单方法,基本上是这样的:echo(str_pad("Live Ping Test!",512));然后开始回显fread的结果。

答案 3 :(得分:1)

您可能希望尝试使用flush()在其准备就绪时刷新输出,并使用passthru()执行命令。

答案 4 :(得分:1)

Carlos C Soto是对的,你必须使用javascript。 EventSource是要走的路。基本上,它的javascript代码将不断调用url

您可以在文件中写入ping的输出,并编写将读取最后一行的php脚本,然后使用eventsource调用此脚本。

在网络上搜索“服务器已发送事件”以查找更多示例

答案 5 :(得分:0)

如果可以使用apache执行用户解析。如果您的root用户不同且服务器用户不同,那么它将不允许执行命令行命令。

答案 6 :(得分:0)

我测试了卡洛斯的答案......

我想添加flush(); ob_flush();让它正常工作(两者都需要冲洗和ob_flush)

像这样

<?php

$proc = popen("ping -c 5 google.com", 'r');
while (!feof($proc))
{
    echo "[".date("i:s")."] ".fread($proc, 4096).'<br>';flush();ob_flush();
}

?>