views:

1000

answers:

3

Hello,

Using PHP on Linux, I'd like to determine whether a shell command run using exec() was successfully executed. I'm using the return_var parameter to check for a successful return value of 0. This works fine until I need to do the same thing for a process that has to run in the background. For example, in the following command $result returns 0:

exec('badcommand > /dev/null 2>&1 &', $output, $result);

I have put the redirect in there on purpose, I do not want to capture any output. I just want to know that the command was executed successfully. Is that possible to do?

Thanks, Brian

+2  A: 

My guess is that what you are trying to do is not directly possible. By backgrounding the process, you are letting your PHP script continue (and potentially exit) before a result exists.

A work around is to have a second PHP (or Bash/etc) script that just does the command execution and writes the result to a temp file.

The main script would be something like:

$resultFile = '/tmp/result001';
touch($resultFile);
exec('php command_runner.php '.escapeshellarg($resultFile).' > /dev/null 2>&1 &');

// do other stuff...    

// Sometime later when you want to check the result...
while (!strlen(file_get_contents($resultFile))) {
    sleep(5);
}
$result = intval(file_get_contents($resultFile));
unlink($resultFile);

And the command_runner.php would look like:

$outputFile = $argv[0];
exec('badcommand > /dev/null 2>&1', $output, $result);
file_put_contents($outputFile, $result);

Its not pretty, and there is certainly room for adding robustness and handling concurrent executions, but the general idea should work.

Adam Franco
Thanks very much for the answers, very helpful.
Brian
+1  A: 

Not using the exec() method. When you send a process to the background, it will return 0 to the exec call and php will continue execution, there's no way to retrieve the final result.

pcntl_fork() however will fork your application, so you can run exec() in the child process and leave it waiting until it finishes. Then exit() with the status the exec call returned. In the parent process you can access that return code with pcntl_waitpid()

stroop
A: 

just my 2 cents, how about using the || or && bash operator?

i.e. exec('ls && touch /tmp/res_ok || touch /tmp/res_bad'); and then check for file existence

vaquerito

vaquerito