尝试在 PHP 到 mysqldump -v 到 popen 并且没有得到输出
Trying in PHP to mysqldump -v to popen and not getting output
我正在为 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
吗?还是我只是错误地重定向了输出?
您似乎实际上将 mysql 转储数据通过管道传输到 mysql,在这种情况下,将错误消息包含到管道中可能不是一个好主意。
当然,在这种情况下,您无法捕获 mysql转储的输出。
您应该使用 tee
命令:
mysqldump -uroot -proot -v dbname | tee /tmp/output | mysql -uroot -proot dbname2
这样,您可以在 mysql 和 /tmp/output
的管道中获得输出。
通过这种方式,您可以 fopen
/tmp/output
获得结果。
请注意,您可能不会在输出中遇到可能的错误,因为 mysql 稍后会不高兴看到它们。
我想通了,不必将文件用作流缓冲区。
/**
* 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
class 到 运行 终端命令并将输出通过管道传递给回调函数。不过显然还有很长的路要走。
感谢您的帮助,@Victor
我正在为 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
吗?还是我只是错误地重定向了输出?
您似乎实际上将 mysql 转储数据通过管道传输到 mysql,在这种情况下,将错误消息包含到管道中可能不是一个好主意。
当然,在这种情况下,您无法捕获 mysql转储的输出。
您应该使用 tee
命令:
mysqldump -uroot -proot -v dbname | tee /tmp/output | mysql -uroot -proot dbname2
这样,您可以在 mysql 和 /tmp/output
的管道中获得输出。
通过这种方式,您可以 fopen
/tmp/output
获得结果。
请注意,您可能不会在输出中遇到可能的错误,因为 mysql 稍后会不高兴看到它们。
我想通了,不必将文件用作流缓冲区。
/**
* 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
class 到 运行 终端命令并将输出通过管道传递给回调函数。不过显然还有很长的路要走。
感谢您的帮助,@Victor