在命令完成之前,shell_exec导致404错误

时间:2015-09-30 17:12:15

标签: php shell-exec

我不是很有经验,所以我可以使用一些帮助来解决这个问题...有点卡住了。 :-(提前致谢:

我正在为电子商务平台开发一个模块。 我在www.mystore.com/modules/mymodule/myscript.php

有一个脚本

myscript.php中的这段代码:

$command = '/do/some/process/ -make_log_files';
echo shell_exec($command);
//here I would like to do some stuff with the log file, now that I know the process has completed.

这一切在理论上都很好。由$command启动的进程将在一段时间后开始并完成(我可以通过它创建的日志文件来判断)。还应注意,没有证据表明script.php访问任何mystore文件。我在mystores中记录了一条最基本的包含文件的消息,如果我只是在shell_exec()之前退出(),我就看不到消息。

由于流程太慢而且需要很长时间才能完成,当我使用浏览器导航到www.mystore.com/modules/mymodule/myscript.php时,浏览器会说“等待mystore.com ...”并继续显示我的正在加载动画。

过了一会儿它会突然显示mystore的404页面。

编辑: 在这种情况下,以下所有内容都毫无用处,我找到了更好的解决方案。

我已经将这些内容添加到script.php的开头,以防止这种情况发生:

ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);
while (@ob_end_flush());
ini_set('implicit_flush', true);
ob_implicit_flush(true);
header("Content-type: text/plain");
header('Cache-Control: no-cache'); 
http_response_code(200);
for($i = 0; $i < 1000; $i++)
{
    echo ' '; //echo 1000 whitespaces
}
ob_flush();
flush();

我没有尝试使用这些其他命令,而是使用相同的结果,或者只是在处理完成之前使用打印和空数组或类似命令,而不是shell_exec。

$process = (popen($command, "r"));
echo "'$process '; " . gettype($process ) . "\n";
$read = fread($process , 2096);
echo $read;
pclose($process );

exec($call,$output);
print_r($output);

passthru($call);

没有人做得更好。

编辑: 原来,因为我在FastCGI上运行,这整个“没有缓冲区将数据直接发送到浏览器”将无法正常工作。

如果在一段时间后调用我的脚本会产生404,我怎么能确保我的过程完成?

我应该注意,我的命令并不以>/dev/null &结尾。因此我故意不把它放在后台。

此外,我已经尝试过我的脚本并更改了命令的参数,以便我的进程非常快。一切都按预期工作。

我意识到还有其他解决方案(cron job或javascript检查日志文件)但是如果我只是希望脚本等待进程完成呢?这不可能吗?

修改

感谢drew010的有用评论,我意识到以下几点:

  • 检查日志文件显示我实际上有500错误,而不是 404
  • 从mystore.com禁用htaccess使其实际显示为500
  • 错误发生在约。 2分钟,可能是由CGI引起的 服务器超时
  • 我决定尝试使用任何CGI设置来简单地直接通过命令行运行我的脚本:

call.php:

exec(php home/usr/mystore.com/modules/mymodule/myscript.php > /dev/null 2>&1 &');
echo 'all things set in motion, you are good to go!';

现在我可以简单地去 www.mystore.com/modules/mymodule/call.php 这将在后台运行脚本!一旦脚本在后台没有超时,我的PHP代码耐心地等待缓慢的过程完成,然后完成其余的工作。 : - )

2 个答案:

答案 0 :(得分:0)

404错误可能是达到某种超时的结果。

Web服务器通常会有CGI超时,如果它们在一定时间内没有收到CGI后端的响应,它们将终止请求。

由于您的脚本运行了一段时间,可能会达到终止连接的超时。

过去我发现这种情况发生了,网站显示的是404,但是当你查看服务器日志时,你会看到一个500错误,表明服务器在超时期限内没有收到来自后端的响应。 / p>

如果可以从终端运行任务,这可能是更好的选择,或者您可以尝试增加超时。在任何情况下,我通常都喜欢我的CGI超时略高于PHP max_execution_time指令,所以它们有点同步。

答案 1 :(得分:0)

404错误从不是超时的结果。

尝试在网络服务器中保持一个进程长时间运行是一个非常糟糕的主意 - 它们不是为工作而设计的。开发人员和管理员将会采取很好的措施来保护系统免受任何看似行为不端的问题。有solutions,但它们引入了其他复杂情况,对此的全面讨论有点超出了帖子的范围。

如果发生超时,那么它应该返回504错误(不是500错误,尽管我们会越来越近)。

您认为解决问题的方法是:

exec('php home/usr/mystore.com/modules/mymodule/myscript.php > /dev/null 2>&1 &');

实际上是在创建更多问题 - 作业可能会随机停止,僵尸进程可能会开始备份,apache进程实例可能会被阻止...