我正在为mysqldump
编写一个包装器,并希望在PHP CLI应用程序中很好地显示输出。
我尝试使用mysqldump -v
运行popen
,以便我可以获得详细输出并向用户显示进度指示器。但是没有返回任何输出(默认情况下,它会通过stdErr
)记录到屏幕上。
我尝试在命令中添加2>&1
以将详细输出从stdErr
推送到stdOut
,但fread
仍然无法获得任何输出,即使输出不再通过stdErr
进入屏幕。
$cmd = "mysqldump -uroot -proot -v dbname 2>&1 | mysql -uroot -proot dbname2";
$handle = popen($cmd, "r");
$buffer = "";
while ($handle && !feof($handle)){
$output = fread($handle, 100);
$buffer .= $output;
echo sprintf("Buffer: %s\n", $buffer);
}
pclose($handle);
我应该使用别的东西而不是popen
吗?或者我只是错误地重定向输出?
答案 0 :(得分:1)
您似乎实际上将mysqldump数据传输到mysql中,在这种情况下,将错误消息包含在管道中可能是个坏主意。
当然,在这种情况下,你无法捕获mysqldump的输出。
您应该使用tee
命令:
mysqldump -uroot -proot -v dbname | tee /tmp/output | mysql -uroot -proot dbname2
这样,你可以在mysql和/tmp/output
的管道中输出。
通过这种方式,您可以fopen
/tmp/output
获取结果。
请注意,您可能没有输出中可能出现的错误,因为mysql在以后的管道中看到它们会不高兴。
答案 1 :(得分:0)
我想通了,不必将文件用作流缓冲区。
/**
* PROCESS
*
* Process the command
*
* @param int $buffer The size of the buffer
* @param int $pipe The pipe to subscribe to (0=stdIn, 1=stdOut, 2=stdErr)
*
* @return bool Success or not
*/
public function process($buffer=10, $pipe=1) {
$handle = proc_open(
$this->command,
[
["pipe","r"],
["pipe","w"],
["pipe","w"]
],
$pipes
);
if (!is_resource($handle)) {
return false;
}
$output = "";
$buffer = "";
$hasLineCallbacks = count($this->onNewLine);
while ($buffer = fread($pipes[$pipe], 10)) {
$output .= $buffer;
if (preg_match("/[\r\n]/", $output)) {
$segments = preg_split("/[\r\n]+/", $output);
while (count($segments) > 1) {
$line = array_shift($segments);
if (!$hasLineCallbacks) { continue; }
foreach ($this->onNewLine as $callback) {
if (!$callback["pattern"] || preg_match($callback["pattern"], $line)) {
call_user_func($callback["callback"], $line);
}
}
}
$output = array_shift($segments);
}
}
proc_close($handle);
return true;
}
我基本上使Background
类运行终端命令并将输出传递给回调函数。它显然还有很长的路要走。
感谢您的帮助,@ Victor