Archive

Posts Tagged ‘file_get_contents’

One Method to Bypass The Bug #11058 of PHP

August 8th, 2009 Iron_Feet 2 comments
分享家:Addthis中国

最近接触PHP很多,由于PHP也就接触了才一年,因此遇到了不少问题,其中当时让我比较头疼是一个因为PHP自身的Bug而引起的麻烦。

开始我是想抓取一个页面的源代码:

<?php
$content = file_get_contents("http://www.iron-feet.cn/");
echo $content;
?>

很简单的代码,当时觉得肯定不会有问题的,但是在我的本机上(环境是IAMP)一运行,报错:

php_network_getaddresses: getaddrinfo failed

当时极其的纳闷,两行代码怎么看都没有错误。于是乎,我将文件上传到我的虚拟主机(环境是LAMP)上,一运行,结果一样让我失望,报相同的错误。
查看了N久,未果。在我百般无奈之下,寻找PHP官网,最后发现这个错误是由于PHP的一个Bug所引起的。
该Bug主要的原因是PHP在某些情况下,无法正确访问DNS。而且这个“某些情况下”目前还不得而知,有些情况下这个Bug就不作祟,有些情况下就开始发作了。这个Bug不但导致了file_get_contents函数的不能正常工作,别的只要需要通过访问DNS实现的函数都会出现这个Bug。
经过多方测试和查看,发现唯一能解决这个错误的方法就是修改hosts,让PHP不需要访问DNS直接通过hosts实现域名解析。
但是这个显然是个治标不治本的方法,因为很多虚拟主机是不会允许用户随意修改hosts,我所使用的这个虚拟主机就是这样的。

我当时就想,我的虚拟主机也有这个Bug,但是我主机里面的Wordpress却很正常的运作着,肯定有别的什么解决的方法。
经过对Wordpress文件的分析,才发现其实解决的方法很容易。当网上那些提问的人都在考虑和寻求如何解决这个Bug的时候,却没有人想过怎么去避开这个Bug。

Wordpress访问网络是通过两套方案的,一套就是上述所说的利用PHP原生的函数;一套就是通过调用curl来实现。
PHP可以通过LibCurl来实现网络的访问和操作,而且比原生的要强很多。

<?php
$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_URL, "http://www.iron-feet.cn");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$contents = curl_exec($ch);
echo $contents;
curl_close($ch);
?>

利用Libcurl几行代码就可以避免PHP的这个原生Bug。也不需要修改hosts了。但是需要肯定的是:您的虚拟主机必须支持Libcurl。

只要通过

<?php
phpinfo();
?>

就可以查看您的主机是否支持Libcurl了

再次可以肯定的是:目前主流的虚拟主机,Libcurl是基本都会支持的,但是hosts是不可能允许你修改的。还是尽量使用Libcurl吧,即使你现在没有遇到这个Bug,也不能保证万一哪天你要把你文件移到别的主机运行不会遇到这个Bug。
同时衷心希望PHP官方能快点Fix掉这个Bug