【问题标题】:Read command line output读取命令行输出
【发布时间】:2017-08-24 14:00:36
【问题描述】:

任何人都可以帮助,如何使用 php 从 linux 中的命令终端输出读取实时输出。

下面是我试过但不工作的代码:

<?php
if (isset($_POST['pyinp'])){
$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>";
}
?>
<!DOCTYPE html>
<html>
<body>
<form action="#" method="POST">
<input name = "pyinp" type="submit">
</form>
</body>
</html>

我得到了提交按钮,当我按下提交时,什么都没有出现。

我是 html 和 php 的新手。我只是在网上编码。

以下代码正在运行:

<!DOCTYPE html>
<html>
<body>
<form action="#" method="POST">
<input name = "pyinp" type="submit">
</form>
<?php
if (isset($_POST['pyinp'])){
$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
);
echo "<pre>";
if( ($fp = popen("ls -l", "r")) ) {
    while( !feof($fp) ){
        echo fread($fp, 1024);
        flush(); // you have to flush buffer
    }
    fclose($fp);
}
}
?>
</body>
</html>

但如果我用 ping 127.0.0.1 替换它不起作用

谢谢

【问题讨论】:

  • 附注:表单的 HTML 语法错误。
  • 您有错误或警告信息吗?什么不起作用,请提供更多详细信息。此外,您的代码开头没有&lt;?php
  • @reporter 和 Benoit Zu,我已经更正了代码
  • html 缺少一个开始 标记。
  • 已添加但无法正常工作

标签: php html linux


【解决方案1】:

TL;DR:在 HTML 文档关闭之前有一个无限循环。


让我重写你的代码,以便 ping 输出进入&lt;body&gt;...&lt;/body&gt; 容器:

<!DOCTYPE html>
<html>
<body>
<form action="#" method="POST">
<input name = "pyinp" type="submit">
</form>
<?php
if (isset($_POST['pyinp'])){
$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>";
}
?>

</body>
</html>

现在,让我们做一个思想实验。第一次GET 页面时,您会看到一个带有按钮的表单。一切都很好。你点击按钮。表单将POSTed 恢复为自身。然后会发生什么?

首先输出静态HTML:

<!DOCTYPE html>
<html>
<body>
<form action="#" method="POST">
<input name = "pyinp" type="submit">
</form>

然后PHP引擎启动:

<?php

然后 PHP 看到按钮被按下,并做了一堆东西来设置管道(所有这些都是正确的,顺便说一句,你可以在命令行上检查):

$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>";

然后它会检查连接是否已建立(您确实应该在此处添加else):

if (is_resource($process)) {

现在呢?

while ($s = fgets($pipes[1])) {
    print $s;
    flush();
}

没错:一个永远不会结束的while循环!这永远旋转和旋转。同时,这些都没有被执行:

?>

</body>
</html>

所以浏览器永远不会看到身体关闭。那你问呢?好吧,在关闭所有标签之前,浏览器没有义务显示内容。

“但是,但是,它有时确实有效!”你喊。当然,有时它会起作用。但这次看起来加载只是停滞,而不仅仅是糟糕的 HTML。浏览器不知道你有一个永远不会结束的无限循环,所以它只是在等你关闭你的输出。

In general:

Web 作者要小心 - 除非您想在 Webkit 容错代码中作为示例出现 - 编写格式良好的 HTML。

如果你想看这个作品,那就不要做无限循环:

$i = 0;
while ($s = fgets($pipes[1])) {
    print $s;
    flush();
    if (4 < $i++) { break; }
}

或者加载 Javascript,回调执行工作的脚本。

【讨论】:

  • 它仍然无法正常工作。单击提交后,注意在帖子中显示添加的更多信息
  • ls 起作用的原因是它的输出在列出所有文件后结束。 ping 永远不会终止,因此你有一个无限循环,浏览器永远不会看到 body 关闭,它会一直等待。将您的命令更改为ping -c 4 127.0.0.1,您将看到输出。
  • 运气不好我使用了 -c 4 选项
  • 什么操作系统运行 PHP?什么浏览器和版本?
  • 好吧,当我将其更改为 $cmd = "ping -c 4 127.0.0.1"; 时,我得到了我所描述的行为:页面运行了几秒钟,然后显示了四个 ping。底线:您无法像使用基本 HTML 在命令行上习惯的那样实时显示输出。您需要切换到异步架构。
最近更新 更多