我正在将一个应用程序转移到一个新服务器。应用程序使用命令行调用,新服务器以CGI/FastCGI的形式运行PHP。
问题:在命令行执行的脚本不是exec命令中提到的文件,而是调用文件本身。
应用程序使用exec()在命令行上运行脚本。calling_script.php的整个代码(从实际应用程序中缩小以演示问题)是:
<?
echo __FILE__;
$test = 1;
shell_exec("/usr/bin/php /path/called_script.php ".$test." >> /path/out.log 2>&1 &");
对于called_script.php,它只是:
<?
echo __FILE__;
var_dump($argv[1]);
实际情况是:calling_script.php被调用,而不是called_script.php-参数也会丢失-calling_scriptphp在一个无限循环中被调用,因为对它的每次调用都会导致另一个exec调用再次在它上执行。我尝试了passthrough和shell_exec而不是exec,得到了相同的结果。
我在一个论坛上找到了这样的解释: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(通过exec()导致启动请求程序的无限循环)
引用:"您正在运行PHP的CGI版本,它会获取脚本名称现在从环境中,而不是从命令行中"更安全"。
有(或应该有)一个ini设置来控制这一点,但是可能希望通过脚本运行PHP的CLI版本相反"
我试图获得PHP的CLI版本,但新服务器由一个提供商管理,没有CLI版本。还有其他解决方案吗?
最终,我想要实现的是php的异步执行——有没有关于在没有CLI版本的php的情况下如何实现这一点的建议?使用CURL、PEAR还是fsockopen?队列或任务队列服务器(如gearman或beanstalkd),如果是,是哪一个?我们衷心欢迎我能够迅速实施的任何解决方案。
为此,您确实应该使用PHP的CLI版本。您可以通过取消设置CGI规范中列出的每个环境变量来偷偷浏览CGI内容。
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");
我也遇到了同样的问题。解决方案很简单。只需添加exit();在系统()调用之后。
适用于我phpfcgi 5.6 Centos,cpanel easy apache 4
系统("/usr/bin/php/path/called_script.php".$test.">>/path/out.log 2>&1&");exit();