无法使用PHP exec执行PHP脚本

16

我正在尝试使用PHP exec调用一个需要几秒钟(涉及第三方的网络服务)的脚本。经过长时间的努力,我已将其简化为经典的Hello World示例。调用脚本看起来像这样:

exec('/usr/bin/php /home/quote2bi/tmp/helloworld.php > /tmp/execoutput.txt 2>&1 &');
当我运行这段代码时,输出的 execoutput.txt 包含了调用脚本页面的副本,而不是像我预期的那样包含 hello world
为什么我不能使用 exec 执行这个 PHP 脚本呢?注意,当我将命令改为类似于 ls -l 这样的内容时,输出会是预期的目录列表。顺便说一下,如果有影响的话,我确实将被调用的脚本 chmod 为755了...
更新 - 我把 exec 调用移到了调用脚本的末尾,至少现在我看不到调用脚本在输出中被执行了。谢谢回答者们,我会尝试一些这些想法。
求助!
谢谢 Steve
6个回答

27

我也遇到了这个问题,结果发现这是PHP中的一个漏洞(#11430)。解决方法是在调用另一个PHP脚本时使用php-cli。因此,您仍然可以使用exec,但在浏览器中调用它时,请改用php-cli而不是php:

exec("php-cli  somescript.php");

这个方法对我有用。


1
这对我也起作用了。但愿我早点看到这个答案,就能解决五个小时的头痛问题了。 - Omar
1
我已经找了好几个小时了,差点就要放弃了。请注意,如果您正在使用PHPSuEXEC,则似乎不需要这样做,但是一旦禁用suexec,您必须按照指定使用php-cli。 - rinogo
2
我也曾经在这个问题上苦苦思索了很长时间。真正的难题是,在Ubuntu上使用exec和"php"似乎可以正常工作,但是当我部署到CentOS服务器时,它就无法工作了。php-cli才是答案,所以非常感谢! - btantlinger
1
解决了三天的头疼问题。我们的测试服务器没有出现这个问题,所以修复它一直是一个重大问题。 - miyasudokoro
太棒了!非常感谢。如果我运行 exec("php somescript.php"),它会占用太多内存,为什么? - Maulik patel
你也救了我的一天。对于没有php-cli命令的服务器,只需使用未被调用脚本使用的PHP二进制文件(例如/usr/bin/php/usr/local/bin/php)。 - Jimmie Lin

16

exec命令的作用是将最右边的命令添加到目标中。如果您在php脚本中有shebang行,则不需要包含php解释器的二进制指令。

如果您只想要脚本的输出,请尝试:

exec('/home/quote2bi/tmp/helloworld.php > /tmp/execoutput.txt 2>&1 &')

但是,如果你不希望错误信息出现在文件中,你应该在输出到文件之前将 STDERR 重定向。像这样:

exec('/home/quote2bi/tmp/helloworld.php 2> /dev/null > /tmp/execoutput.txt')
以上内容应该只将“Hello World”输出到execoutput中。
编辑:有趣的是你得到了这种行为。你说“ls”命令起作用了。尝试为此创建一个别名,并将其转发到文件中,如下所示: alias pexec='php /home/quote2bi/tmp/helloworld.php' 然后
exec('pexec > /tmp/execoutput.txt 2>&1 &')

看起来问题出在exec处理输入的方式与shell本身不同。

-John


1
John - 感谢您的回复,但不幸的是,对我没有起作用。当我尝试:exec('/home/quote2bi/tmp/helloworld.php > /tmp/execoutput.txt 2>&1 &')...我得到了相同的结果(输出文件中的当前页面)。第二个 exec 被阻止了(缺少 &)- 添加后我得到了相同的结果。 - Steve
如果我的服务器禁用了exec()函数,有什么选项吗? - Rohitashv Singhal

8
问题出在 PHP 本身,它将脚本中的所有内容都视为 $argv。它不会将输出重定向到文件或 /dev/null。
我曾经遇到过相同的问题。我的解决方法是在 /opt/php-bin 中创建一个 runscript.php 文件,然后在该脚本中运行应该运行的内容。类似这样:
$script = $argv[1]
$params = implode(' ', array_slice($argv, 2));
$cmd    = "{$script} {$params} > /dev/null &";

$output = array();
$return = 0;
exec("php {$cmd}", $output, $return);

exit((int)$return);

然后你可以使用以下方式进行调用:

exec('/opt/php-bin/runscript.php /path/to/your/script.php arg1 arg2')

这是我唯一让它正常工作的方法。


0

如果你只是简单地运行一个 PHP 脚本,执行整个代码的一种可能的方式是使用 include() 函数,它将运行 PHP 文件并输出任何结果。你不能将输出定向到文本文件,但如果你的 Hello World PHP 脚本看起来像这样,它应该会出现在浏览器窗口中:

<?php echo "Hello World!"; ?>

然后它将在浏览器中输出。因此,您的第二段代码将如下所示

<?php include("helloWorld.php");  echo " PHP ROCKS";?>

导致页面看起来像这样,
你好世界!PHP太棒了

0

这个程序运行起来就像你从浏览器中运行脚本一样。

这是在Linux平台上开发项目时遇到的。

exec('wget http://<url to the php script>)

希望这可以帮助!!

0
为了避免PHP在这个领域中的问题,为什么不将其放在shell脚本中?然后PHP可以执行内部处理所有重定向的shell脚本。
如果您需要动态更改内容,那么为什么不编写shell脚本,然后执行它(当然,在此之后进行清理)?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接