PHP exec() return value for background pro

2019-01-29 02:19发布

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

3条回答
乱世女痞
2楼-- · 2019-01-29 02:28

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()

查看更多
Deceive 欺骗
3楼-- · 2019-01-29 02:28

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

exec('ls && touch /tmp/res_ok || touch /tmp/res_bad');

And then check for file existence.

查看更多
forever°为你锁心
4楼-- · 2019-01-29 02:35

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.

查看更多
登录 后发表回答