问题
I'm transfering an application to a new server. The application uses command line calls, and the new server runs PHP as CGI/FastCGI.
Problem: The script that gets executed on command line is not the file mentioned in the exec command, but the calling file itself.
The application uses exec() to run scripts on the command line. Entire code of calling_script.php (scaled down from actual application to demonstrate the issue) is:
<?
echo __FILE__;
$test = 1;
shell_exec("/usr/bin/php /path/called_script.php ".$test." >> /path/out.log 2>&1 &");
For the called_script.php it simply is:
<?
echo __FILE__;
var_dump($argv[1]);
What does happen is: calling_script.php is called, instead of called_script.php - and the Parameter gets lost as well - calling_script.php gets called in an infinite loop, as each call to it causes another exec call that is executed on it again. I tried passthrough and shell_exec instead of exec - with the same results.
I found this explanation in a forum: http://www.mombu.com/php/php-5-forum/t-24759-exec-or-system-et-all-cause-an-infinite-loop-of-starting-requested-program-8469354.html (via exec() cause an infinite loop of starting requested program )
Quote: "You are running the CGI version of PHP and it picks up the script name from the environment now, rather than from the command line as it is "more secure".
There is (or should be) an ini setting to control this, however, you probably want to be running the CLI version of PHP from your scripts instead."
I tried to get my hands on the CLI version of PHP - but the new server is managed by a provider and has no CLI version. Are there any other solutions?
Eventually, what I want to achieve is asynchonous execution of php - any recommendation on how i might achieve that without the CLI version of PHP? Use CURL, PEAR or fsockopen? Queue or task queue servers (such as gearman or beanstalkd) and if so which one? Any solution that I can implement quickly is heartily welcome.
回答1:
You really should use the CLI version of PHP for this. You may be able to sneak around the CGI stuff by unsetting each of the environmental variables that are listed in the CGI specification.
http://en.wikipedia.org/wiki/Common_Gateway_Interface
<?php
$cmd = array();
// Explicitly clear CGI variables from the environment. This relies on "E" being
// set in your http://www.php.net/manual/en/ini.core.php#ini.variables-order
foreach ($_ENV as $k => $v) {
if (preg_match(
'/^(HTTP_|REQUEST_|SERVER_|PATH_|DOCUMENT_ROOT|GATEWAY_INTERFACE)/', $k)) {
$cmd[] = "$k=''";
}
}
// Generates a command like: "GATEWAY_INTERFACE='' /usr/bin/php myscript.php"
$prefix = implode($cmd, ' ');
shell_exec("$prefix /usr/bin/php myscript.php");
回答2:
Well I had the same issue. The solution was simple. just add exit(); after the system() call.
Works for me phpfcgi 5.6 Centos, cpanel easy apache 4
system("/usr/bin/php /path/called_script.php ".$test." >> /path/out.log 2>&1 &"); exit();
来源:https://stackoverflow.com/questions/18067482/php-cgi-replaces-name-of-called-file-in-command-line-exec-calls-causing-infinit