使用实时更新的PHP shell_exec

7

我有一个shell程序,想通过php执行。问题是它可能需要很长时间,因此需要实时更新到用户的浏览器。

我看到可能需要使用popen()来实现,但我在PHP方面有些(好吧,其实非常)菜,不知道如何实现。

感谢任何帮助!

5个回答

17
if( ($fp = popen("your command", "r")) ) {
    while( !feof($fp) ){
        echo fread($fp, 1024);
        flush(); // you have to flush buffer
    }
    fclose($fp);
}

1
为什么你必须刷新缓冲区? - dellsala

3

有一个非常简单的选择,但这个方法可能不是很优雅。

`yourcommand 1>&2`;

将标准输出重定向到标准错误输出。


2

有两种可能的行为:

  1. 非阻塞,需要在刷新之间执行其他操作(@GameBit展示了如何实现)。

  2. 阻塞,等待调用命令完成,这种情况下可以使用passthru函数


我该如何使用passthru来实现呢?另外,如果在刷新之间不需要执行任何操作,使用@GameBit的代码是否有任何缺点? - EduAlm
你可以使用popen传递与解决方案中相同的命令,但来自外部程序的输出直接进入输出流...如果你知道fopen和readfile之间的区别,实际上它们是一样的,只不过是针对进程而言。首先允许你逐字节读取并放入变量中,处理数据,然后进行另一个简单的读取并直接写入输出,无需任何操作。 - Paulo H.
知道了。实际上使用起来更容易。谢谢!:D - EduAlm

0

我使用了这个解决方案。对我来说很好用。

$commandString = "myexe";

# Uncomment this line if you want to execute the command in background on Windows
# $commandString = "start /b $commandString";

$exec = popen($commandString, "r");

# echo "Async Code Test";

while($output = fgets($exec, 2048))
{
    echo "$output <br>\n";
    ob_flush();
    flush();
}

pclose($exec);

-1
尝试这段代码(在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();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接