4

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.

codewaggle
  • 4,893
  • 2
  • 32
  • 48
  • Totally go for the `proc_open` solution, as it seems to give you exactly what you seem to need -- direct access to stderr. Kinda. I'm actually not sure how it reacts to piped commands. I expect you'll get the *gzip* stderr, not the mysqldump stderr... – Charles Jan 02 '13 at 09:29
  • I should have said or "try" to use `proc_open()`, I'm thinking I'll have the same problem as when the `return_var` from exec returns the status of gzip. – codewaggle Jan 02 '13 at 09:33
  • Yeah, almost certainly. Do you have enough disk space and allotted time to do the gzip as a separate command? – Charles Jan 02 '13 at 09:34
  • 1
    Yes, I'm just trying to see if there is a cleaner way. – codewaggle Jan 02 '13 at 09:40

1 Answers1

1

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.

Community
  • 1
  • 1
exussum
  • 18,275
  • 8
  • 32
  • 65
  • I appreciate your response and the question you pointed out has a good overview of using `proc_open`, it's just not a good fit for what I'm trying to accomplish. – codewaggle Jan 02 '13 at 10:26
  • How about using pipestatus with bash -c ? `system("bash -c 'your_command ; exit \${PIPESTATUS[0]}'", $return);` – exussum Jan 02 '13 at 10:37
  • That's awesome, it does exactly what I'm looking for. Please put it in your answer so I can accept it and anyone else who's looking will see it. I did a search on bash `PIPESTATUS` so I could understand how it worked and found a post specific to using mysqldump piped to gzip, too bad I didn't know what to look for to begin with. I'll put the link in my question, but if you explain it in your answer, people won't need to bother clicking on the link. – codewaggle Jan 02 '13 at 11:29