linux - Trying in PHP to mysqldump -v to popen and not getting output

200

I'm writing a wrapper formysqldump and want to show the output nicely in a PHP CLI application.

I'm attempting to runmysqldump -v usingpopen so that I can get the verbose output and display progress indicators to the user. However no output is returned (by default it gets logged to the screen viastdErr).

I tried adding2>&1 to the command to push the verbose output fromstdErr tostdOut, butfread still doesn't get any output even though the output nolonger goes to the screen viastdErr.

$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);

Should I use something else instead ofpopen? Or am I simply incorrectly redirecting the output?

879

Answer

Solution:

You seem to actually pipe the mysqldump data into mysql, in which case it might be a bad idea to include error messages into the pipe.

Of course, in this scenario, you cannot capture the mysqldump's output.

You should use thetee command:

mysqldump -uroot -proot -v dbname | tee /tmp/output | mysql -uroot -proot dbname2

This way, you can have the output both in pipe for mysql and/tmp/output. In such a way you can thenfopen/tmp/output for results.

Please note that you might not have the possible errors in the output, as mysql would not be happy seeing them later down the pipe.

459

Answer

Solution:

I figured it out, without having to use a file as a stream buffer.

/**
 * 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;
}

I'm basically makingBackground class to run a terminal command and pipe the output to callback functions. It obviously still has a long way to go though.

Thanks for your help, @Victor

People are also looking for solutions to the problem: php - Load external HTTPS script in HTTP WordPress site

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.