我正在将应用程序转移到新服务器。该应用程序使用命令行调用,新服务器将PHP作为CGI / FastCGI运行。
问题:在命令行上执行的脚本不是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_script.php,因为每次调用它都会导致再次执行另一个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() cause an infinite loop of starting requested program)
Quote:“你正在运行PHP的CGI版本,它现在从环境中获取脚本名称,而不是从命令行,因为它”更安全“。
有(或应该)ini设置来控制它,但是,您可能希望从脚本中运行PHP的CLI版本。“
我试图了解PHP的CLI版本 - 但新服务器由提供商管理,没有CLI版本。还有其他解决方案吗?
最终,我想要实现的是异步执行php - 关于如何在没有CLI版本的PHP的情况下实现这一目标的任何建议?使用CURL,PEAR还是fsockopen?队列或任务队列服务器(如gearman或beanstalkd)以及如果是哪一个?我能够快速实施的任何解决方案都热烈欢迎。
你真的应该使用CLI的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();在system()调用之后。
适合我的phpfcgi 5.6 Centos,cpanel easy apache 4
system(“/ usr / bin / php /path/called_script.php”。$ test。“>> / path / out.log 2>&1&”);出口();