问题:我正在目睹一个随机的情况,即ob_get_conents()什么都不返回,什么时候它什么都没有。每天都有成千上万的成功失败。随机
基础:我使用输出缓冲和写入文件将特定的HTML生成输出包装到变量中。然后,在使用新的HTML构建刷新文件之前,将此文件抛出到所有后续命中X分钟。它是一个基本的内联缓存构建器,它固定在较旧的站点代码上。
在目击了一些空页的问题后,我追踪到ob_get_contents()没有为给定的刷新运行返回任何内容。当它下次刷新时,通常都可以。然后,几小时后再次出现空的,空的回归(从未在'同一时间')。
这让我很生气,因为它不一致。当ob_get_contents()的返回为空时,我有php动作给我发电子邮件...带有一堆细节。似乎没有什么能够解释“为什么”。
将代码的复杂版本减少到其核心之后...这就是造成问题的原因:
ob_start();
// A lot of html generation code which would normally just output ...
// This html will ALWAYS have content ...
$guts = ob_get_contents();
if ( empty($guts) ) { /* email me a failure notice! */ }
ob_end_clean();
// write $guts to file and echo ...
其他一些细节:
大多数是这类代理(所有随机IP):
请注意: 总是像其他关于ob_get_contents()的堆栈问题一样返回空。我读过那些,没有帮助......我希望它一直都是,那么这将是一个明显的解决方案。
答案 0 :(得分:2)
我几个月来一直在同一个PHP版本(5.5.9)上看到类似的问题。也无法切换到其他PHP版本。 我一直在努力在我们的系统中检测到这一点,但幸运的是现在能够追踪并利用它。
在PHP 5.5.9中,函数print_r
在内部使用输出缓冲,此版本中报告了有关print_r
和输出缓冲的错误。
所以这就是你需要做的......
<?php
ignore_user_abort(true);// (curl disconnects after 1 second)
ini_set('max_execution_time','180'); // 3 minutes
ini_set('memory_limit','512M'); // 512 MB
function testPrint_r($length)
{
$test1 = array('TEST'=>'SOMETHING');
$test2 = print_r($test1, true);
$test3 = "Array\n(\n [TEST] => SOMETHING\n)\n";
if(strcmp($test2, $test3)!==0) {
throw new Exception("Print_r check failed, output length so far: ".$length);
// consult your error.log then, or use some other reporting means
}
}
$message = "123456789\n";
$length = strlen($message);
while(1)
{
echo $message;
$total_length += $length;
testPrint_r($total_length);
}
die('it should not get here');
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://some.server/first.php');
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_exec($ch);
curl_close($ch);
echo "all done";
第一个脚本只是在循环中输出一些字符。它通过每次迭代回显10个字符来实现。如果您只是调用此脚本,它将在配置的时间后始终超时。
第二个脚本使用CURL调用第一个脚本,但是以断开的方式调用(1秒)。这就是为什么第一个脚本包含忽略用户中止的原因。
不知何故,很可能是由于某些特定于php版本5.5.9的bug,在大约1.8MB的数据已经被回显之后,print_r因此任何额外的输出缓冲使用中断。带有第二个参数TRUE的Print_r只返回任何内容。很可能一些内部或系统端缓冲区耗尽,其他字符不能放在任何地方,或者已经回显的字符被删除。不知道。我无法在阈值编号和phpinfo的任何配置设置之间找到相关性。输出缓冲在我们的系统中没有设置值。
因此可能是某些CURL / WGET被使用和断开连接,或者只是在开始时使用和断开了普通浏览器。像“Ruby”,“FeedBurner”这样的名字对我而言就像是libs或机器人。
a)如果您的脚本不是太复杂,请尝试在PHP 5.5.9,print_r中避免输出缓冲。 var_export很好,工作方式不同。
b)在生成输出时,用字符串连接替换回声,直接写入文件。如果你使用smarty,那么这可能是不可能的,因为smarty在内部使用输出缓冲很多。
c)或者创建一个禁用代理列表,如果它们是这些失败的主要原因。
d)顺便说一下。如果ob_get_level()返回2,则表示默认情况下打开输出缓冲在系统中。我认为你不需要那个任务,关闭它可能甚至可以帮助你。值得一试。
尝试在您的系统上运行相同的脚本,并告诉我您的max.echoed大小是多少。
答案 1 :(得分:0)
您可以解决具有重建文件的cron作业的问题,并仅在成功时保存它,并且服务器仅提供静态文件。你会更新得到这样的空页。
答案 2 :(得分:0)
我想我通过将 php_flag output_buffering On
行添加到我的 .htaccess
文件中解决了类似的问题。就我而言,我的 PHP 文件首先包含 HTML 代码,然后是一个调用 ob_get_contents
命令的 PHP 块。有时这个 ob_get_contents 的结果是空的。我不确定这是否总是有效,或者为什么。