使用shell命令返回的每一行获取PHP更新

时间:2011-08-29 21:36:01

标签: php bash exec

背景 我正在尝试使用php编写一个shell脚本,它将自动检出几个大型SVN repos。我也使用PEAR控制台进度条类来显示结帐的进度(不是完全必要的,但是提示我的问题)。

问题: 有没有办法运行一个循环,它会在命令行上用STDIN的每一行输出更新?

如果我这样做

<?php shell_exec("svn co svn://my.repo.com/repo/trunk"); ?>

我从一个巨大的字符串中取回命令的所有输出。 尝试像

这样的循环
   <?php     $bar = new Console_ProgressBar('%fraction% [%bar%] %percent% | %elapsed% :: %estimate%', '=>', ' ', 80, $total);
    $bar->display(0);
    stream_set_blocking(STDIN, 0);
    $output = array();
    $return = '';
    exec("svn co $svnUrl $folder", $output, $return);
    while (!isset($return))
    {
        $bar->update(count($output));
    }
    $bar->erase(); ?>

将显示栏但不会更新。

任何解决方案?

========================= UPDATE ================== =====================

这是我根据答案提出的工作代码(供将来参考):

    <?php    
    $bar = new Console_ProgressBar('%fraction% [%bar%] %percent% | %elapsed% :: %estimate%', '=>', ' ', 80, $total);
    $handle = popen("/usr/bin/svn co $svnUrl $folder", 'r');
    $elapsed = 0;
    $bar->display($elapsed);

    while ($line = fgets($handle))
    {
        $elapsed++;
        $bar->update($elapsed);
    }
    pclose($handle);
    ?>

3 个答案:

答案 0 :(得分:4)

PHP不是多线程的。 exec()和公司将阻止您的脚本,直到exec'd任务完成。使用while()循环是没有意义的,因为在svn调用完成之前,循环甚至不会开始运行。

如果你想运行多个并行的svn,你需要使用popen()(或proc_open()),这会给你一个文件句柄,你可以从中读取外部命令的输出,并且有多个这样的外部命令同时进行。

答案 1 :(得分:0)

答案 2 :(得分:0)

我理解你的问题是php同步执行脚本。这意味着只有在exec命令和输出不会因为已经完成而改变之后才会运行循环。尝试使用fork。