phperror-handlingexecmysql

Run mysqldump via php exec(), pipe to gzip, return mysqldump stderr


See bottom for solution

I'm running mysqldump as part of a php script called via cron job.

Is it possible to return stderr from the mysqldump command, maybe assign it to a variable that can be read directly? Or is it possible to assign stderr to the output or return_var of the exec() command?

The basic commands being used:

$dump_cmd = 'mysqldump -u username -pPassword db_name --tables db_table --where="field1 = abc" | gzip -c > dumpfile.sql.gz';

exec( $dump_cmd, $dump_cmd_output, $dump_cmd_return_var );

output and return_var from exec() aren't helpful:

$dump_cmd_output is empty because the output is piped to gzip.

$dump_cmd_return_var shows the return status from gzip.


I'm aware of other approaches to see if there were any errors raised while mysqldump was running:

I can just do the dump without gzipping it, check $dump_cmd_return_var for the return status and then run gzip as an additional command.

$dump_cmd = 'mysqldump -u username -pPassword db_name --tables db_table --where="field1 = abc" --result-file="dumpfile.sql"';

$zip_cmd = 'gzip dumpfile.sql';

exec( $dump_cmd, $dump_cmd_output, $dump_cmd_return_var );

if($dump_cmd_return_var == 0) {
  exec( $zip_cmd, $zip_cmd_output, $zip_cmd_return_var );
}

I can send stderr from mysqldump to a file by using the --log-error=dump_errors.txt option of mysqldump:

$dump_cmd = 'mysqldump -u username -pPassword db_name --tables db_table --where="field1 = abc" --log-error=dump_errors.txt | gzip -c > dumpfile.sql.gz';

Or by sending stderr to a file before the pipe 2> dump_errors.txt:

$dump_cmd = 'mysqldump -u username -pPassword db_name --tables db_table --where="field1 = abc" 2> dump_errors.txt | gzip -c > dumpfile.sql.gz';

Or I could try to use proc_open(). Though I expect that I'll have the same problem I'm having with exec(), the return status of the executed command (return_var) shows the status returned by gzip.


It would be cleaner (less complex) if any errors were returned directly or sent to a variable accessible from the script, so I'm curious if this is possible.


Solution:

@user1281385 has a great solution. In order to better understand it, I did a search for:
"bash PIPESTATUS[0]"

One result used this exact scenario (mysqldump piped to gzip). Here's the link for anyone who want's more info:
Bash - How to check the exit status of pipe command

Here's how I'm using it:

$dump_cmd = 'mysqldump -u username -pPassword db_name --tables db_table --where="field1 = abc" | gzip -c > dumpfile.sql.gz';

system("bash -c '".$dump_cmd." ; exit \${PIPESTATUS[0]}'", $dump_cmd_return);

if($dump_cmd_return == 0) {
  Do some other stuff;
}

Basically, the mysqldump command is the first one performed, so its return value is stored as the first value ( key [0] ) of the PIPESTATUS array.


Solution

  • proc_open is the only way ive used

    PHP StdErr after Exec()

    A similar question

    if its just the stderr your after you could redirect stdout to nowhere and stderr to stdout

    Or use PIPESTAUS

    system("bash -c 'your_command ; exit \${PIPESTATUS[0]}'", $return);

    Pipe status needs to be called though something sh compatible. In this case bash.

    bash -c runs a command though bash and the PIPESTATUS will show an array of each part of the pipe.