Get exit status of piped commands in PHP

Tags: php bash
By : aross
Source: Stackoverflow.com
Question!

I've got a PHP script that calls the system shell with a piped command. In this case we're talking about a backup script (but it could be anything, I'm asking specifically about the exit status!):

exec(
    "mysqldump --user=$u --password=$p --host=$h --port=$p $db | gzip -9 > backup.sql.gz",
    $out,
    $status
);

Now I want to know if the mysqldump command yielded an error, but the $status variable always seems to contain 0, even if I force an error. It appears to be the exit code of the second command (gzip in this case). I want to be able to see the exit status of the first command in PHP.

By : aross


Answers

I've managed to think of a more generic solution that makes the exit status of each command in the pipe available to PHP. Of course it requires a shell with $PIPESTATUS (this excludes plain sh).

// The command with pipes.
$command = 'command1 | command2 | echo Test | gzip -9 -f';

// Execute the command. The overall exit code is in $exitStatus.
exec(
    $command . '; echo -e "\n"${PIPESTATUS[*]}',
    $out,
    $exitStatus
);

// Get the exit statuses and remove them from the output.
$pipeStatus = explode(' ', array_pop($output));

print_r([$pipeStatus, $out]);
// [
//   [
//     "127",
//     "127",
//     "0",
//     "0",
//   ],
//   [
//     b"\x1F‹\x089f?
By : aross


You'll need a little help from the Bash internal array PIPESTATUS. This holds the exit status of each command in the pipe. Since you're looking for the first command's exit status you would be addressing PIPESTATUS[0]. So you're code would look like:

exec(
    "bash -c 'mysqldump --user=$u --password=$p --host=$h --port=$p $db | gzip -9 > backup.sql.gz; exit \${PIPESTATUS[0]}'",
    $out,
    $status
);

Note, this changes the overall exit status of the exec() call and you'll need additional code if you want to catch a failure in a longer chain of commands.



This video can help you solving your question :)
By: admin