如今LNMP架構很流行,php
然而有時咱們會遇到一個莫名其妙的問題,nginx
就是咱們訪問php頁面時服務器返回"HTTP/1.1 500 Internal Server Error"錯誤web
這個錯誤讓人匪夷所思,還覺得是nginx出問題了呢?chrome
實際上是php代碼語法錯誤致使的api
默認狀況下,若是被訪問的php腳本中包含語法錯誤,服務器會返回一個空的「200 ok」頁面安全
在php.ini中的fastcgi.error_header選項容許在這種狀況下產生一個HTTP錯誤碼服務器
以使web服務器能夠正確攔截並處理這個錯誤碼,相似直接在php代碼中調用header()返回500狀態碼,如cookie
header("HTTP/1.1 500 Internal Server Error");session
經過php源碼也能夠看出來,本次使用的php版本是:php-5.3.26架構
源文件是:php-5.3.26/main/main.c
第1110行,以下:
if(!PG(display_errors) && !SG(headers_sent) && SG(sapi_headers).http_response_code == 200){ sapi_header_line ctr = {0}; ctr.line = "HTTP/1.0 500 Internal Server Error"; ctr.line_len = strlen(ctr.line); sapi_header_op(SAPI_HEADER_REPLACE, &ctr TSRMLS_CC); }
經過if條件能夠得知,在知足 display_errors=0 和 headers_sent=0即空白頁和
http_response_code=200的條件下返回500錯誤
初看這個500錯誤容易誤認爲nginx出錯,能夠適當調整爲其它響應碼
只要在php.ini中設置 fastcgi.error_header 選項便可,如返回503:
fastcgi.error_header = "HTTP/1.1 503 PHP Parse Error"
這樣就能夠顯示出錯誤的根本緣由,能夠在部署LNMP時加上
沒加這個選項時,能夠經過下面方法調試:
將訪問出錯的頁面拷貝一個,成測試文件,防止影響線上業務和安全問題
如:cp index.php index.test.php
打開 display_errors 選項,在文件開頭加入以下內容:
ini_set('display_errors','1'); error_reporting(E_ALL);
這樣就能夠將錯誤暴露出來,完畢!
前幾天就遇到了這個500錯誤問題,狀況是這樣的:
有開發人員說網站訪問出現500錯誤,他說ie和chrome都訪問不了,只有firefox能夠訪問,我本身也試了試,ie和chrome確實不能訪問,我機器沒裝firefox,因此沒試,我忽然想起之前公司也遇到過這個問題,因此想到了cookie的問題,就上服務器上排查php程序代碼,最後發現這麼一段代碼:
protected function __construct($domain){ ... session_name(self::sess_name); $this->sess_id = empty($_COOKIE[session_name()]) ? $this->gen_sid() : $_COOKIE[session_name()]; ... } private function gen_sid(){ return md5(uniqid(microtime() . getClientIP(), true)); }
當程序執行到第9行的時候就會發生500錯誤,最大的可能就是 getClientIP 函數致使的,直接調用這個函數仍然返回500錯誤,用var_dump(function_exists('getClientIP'))調試,輸出false,問題就在這裏了,定義好這個函數就解決了。但是爲何firefox能夠訪問,而ie和chrome不能訪問呢?這是由於firefox裏面存在cookie了,而ie和chrome都是第一次訪問,沒有cookie,那爲何沒有cookie就會出現這個問題呢?這要歸責於:
$this->sess_id = empty($_COOKIE[session_name()]) ? $this->gen_sid() : $_COOKIE[session_name()];
第一次訪問沒有cookie,因此empty($_COOKIE[session_name()])爲true,
就會調用$this->gen_sid(),就會出現上面找不到getClientIP函數的錯誤,而cookie存在的話就不會調用$this->gen_sid(),而是返回冒號後面的$_COOKIE[session_name()],就沒問題了,呵呵!其實這麼排查有點囉嗦,直接打開錯誤報告,錯誤就會顯現出來,如:
ini_set('display_errors','1'); error_reporting(E_ALL);
顯示以下錯誤信息,很容易就發現問題了,good
Fatal error: Call to undefined function getClientIP()
另外在 php-fpm.conf 中設置的php.ini選項優先於在php.ini中設置的選項,如
在 php.ini 中設置 display_errors = on
在 php-fpm.conf 中設置 php_flag[display_errors] = off
那麼結果是 off