php服務nginx不能使用file_get_contents的解決方案

來源:互聯網
上載者:User
在Windows環境下搭建了一個本地開發服務環境,使用Nginx做服務,但是在使用file_get_contents()擷取本地的連結時出現了錯誤,下面的文章將給大家介紹關於這個問題的解決方案。

一、問題說明

在Windows環境下搭建了一個本地開發服務環境,使用Nginx做服務,但是在使用file_get_contents()擷取本地的連結時http://127.0.0.1/index.php,出現了這樣的錯誤:

file_get_contents(http://127.0.0.1/index.php) [<a href='function.file-get-contents'>function.file-get-contents</a>]: failed to open stream: HTTP request failed!

本地電腦php環境為:nginx+php+mysql;於是找到這篇文章做個筆記,記錄下!

這兩天一直在搞windows下nginx+fastcgi的file_get_contents請求。我想,很多同學都遇到當file_get_contents請求外網的http/https的php檔案時毫無壓力,比如echo file_get_contents(‘http://www.baidu.com’) ,它會顯示百度的頁面。但當你請求localhost/127.0.0.1本網的php服務時卻一直是timeout,無論你將請求時間和指令碼已耗用時間多長都無法返回資料,如file_get_contents(‘http://localhost/phpinfo.php’) 。然而當你嘗試請求html這樣的靜態檔案時卻完全沒有問題。是什麼原因呢?!

首先,我們知道file_get_contents/curl/fopen開啟一個基於tcp/ip的http請求時,請求資料發送到nginx,而nginx則委託給php-cgi(fastcgi)處理php檔案,一般情況fastcgi處理完一個php請求後會馬上釋放結束訊號,等待下一個處理請求(當然也有程式假死,一直佔用資源的情況)。開啟nginx.conf,我們看到下面這一行:

location ~ .php {        fastcgi_pass   127.0.0.1:9000;        fastcgi_index  index.php;        fastcgi_param  SCRIPT_FILENAME  d:/www/htdocs$fastcgi_script_name;        include        fastcgi_params;}

上面已經清楚地看到,所有使用php結尾的檔案都經過fastcgi處理,而在php.ini的設定檔中也有一句:

cgi.force_redirect = 1

表明,所有php程式安全地強制轉向交給cgi處理。

但在windows中,本地127.0.0.1:9000怎樣與php-cgi聯絡的呢?!答案是增加一個php-cgi進程,用它來監聽127.0.0.1:9000。通過控制器命令:

RunHiddenConsole.exe D:/www/php/php-cgi.exe  -b 127.0.0.1:9000 -c C:/WINDOWS/php.ini

我們就可以在啟動windows時,開啟一個php-cgi.exe進程監聽來自127.0.0.1:9000 的請求。在dos命令下開啟netstat –a就可以看到本機電腦下的9000連接埠處於listening狀態(也就是空置,如果沒有發送任何請求的話)。

好了,該說說在php中使用file_get_contents()、curl()、fopen()函數訪問localhost時為什麼不能返回結果。我們再來實驗在index.php中加入file_get_contents(‘http://127.0.0.1/phpinfo.php’) 語句向phpinfo.php發送一個請求,這時瀏覽器中的狀態指示一直在打轉,表示它一直在工作中。開啟Dos中的netstat命令,可以看到本地的9000連接埠的狀態為:ESTABLISHED,表示該進程在聯機處理中。實際上,這裡我們已經同時向nginx發送了兩個基於http的php請求,一個是解析index.php,而另一個是phpinfo.php,這樣矛盾就出來了,因為我們的windows系統只載入了一個http進程,因此,它無法同時處理兩個php請求,它只能先處理第一個請求(index.php),而index.php卻又在等待phpinfo.php處理結果,phpinfo.php沒人幫它處理請求,因為它一直在等待index.php釋放結束訊號,因此,造成了程式的阻塞狀態,陷入了死迴圈。所以我們就看到了瀏覽器的狀態指示一直在打轉。Curl()與fopen函數的原因也相同。

二、解決方案

找到了原因,我們也就有瞭解決辦法。

一是,向系統增加一個http請求,當一個php-cig內要載入另一個請求時,它能夠分配其它http處理額外的php請求。這時需給另一個http sever分配不同的連接埠,比如8080。nginx的案例如下:

http {      server {          listen          80;          server_name     127.0.0.1;          location / {              index index.php;              root  /web/www/htdocs;          }      }      server {          listen          8080;          server_name     127.0.0.1;          location / {              index index.html;              root  /web/www/htdocs;          }      }      include    /opt/nginx/conf/vhosts/php.conf;  }

這樣,連接埠80與8080可以分別處理不同的程式,比如:
test.php

 echo file_get_contents('http://localhost:8080/phpinfo.php');

當然,在*unix下有更多選擇,比如fork。

另外提醒下,網上有人說,通過去掉地址中的http://協議標記,而使用相對位址就規避函數的檢查,實際情況是不是這樣呢?!當在index.php中使用file_get_contents(‘phpinfo.php’); 時,我們可以看到函數輸出了phpinfo.php的原始碼,相當於file_get_contents(‘file:c:wwwphpinfo.php’); ,它實際上只是讀取你的常值內容,因為file_get_contents()函數首先是處理file協議的,而curl則直接報錯無法解析。因此這些人純粹是不學無術的騙子。

還有人提出修改hosts檔案,增加localhost www.xxx.com影射關係,函數通過www.xxx.com訪問本地php,這其實也是不治本的偏方,因為這隻是方便電腦的dns解析,最終www.xxx.com交給127.0.0.1,而後者交給唯一http,還是阻塞。

相關推薦:

file_get_contents函數不能使用的解決方案

PHP串連Nginx伺服器並解析Nginx日誌的方法

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.