背景 我正在尝试使用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);
?>
答案 0 :(得分:4)
PHP不是多线程的。 exec()和公司将阻止您的脚本,直到exec'd任务完成。使用while()循环是没有意义的,因为在svn调用完成之前,循环甚至不会开始运行。
如果你想运行多个并行的svn,你需要使用popen()(或proc_open()),这会给你一个文件句柄,你可以从中读取外部命令的输出,并且有多个这样的外部命令同时进行。
答案 1 :(得分:0)
使用输出缓冲
见:
并看到一些相关的内容:
答案 2 :(得分:0)
我理解你的问题是php同步执行脚本。这意味着只有在exec命令和输出不会因为已经完成而改变之后才会运行循环。尝试使用fork。