尝试在 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