如何排查Web伺服器HTTP ERROR 500的錯誤?

威靈頓發表於2018-11-13

這兩天遷移了一個過去的Web服務到另外一個伺服器,本來按照提前設定的步驟,操作結果都很順利。但是誰想,遷移完成內部測試,“咣”,HTTP ERROR 500。

enter image description here

這是一個基於Linux + Nginx + PHP框架的系統。根據我的經驗,這種錯誤基本上都是後端的PHP指令碼問題導致的。它報錯之後,出於安全防護考慮,PHP-FPM直接返回了500 error,就是報告內部伺服器錯誤給Nginx,瀏覽器就看到了提示。

這種問題,要排查出來,首要的一個步驟就是儘可能的在減少安全隱患的情況下,蒐集錯誤資訊。Web系統因為安全原因,線上的錯誤提示都是關閉的。但是也有辦法單獨的給出現問題的系統開啟。軟體問題錯綜複雜,影響因素很多,必須儘快隔離錯誤、定位問題原因。

對於PHP系統,有好多處會影響錯誤日誌的輸出。有個建議是:對於修改的配置,先做個備份。使用日誌檔案,記錄你剛才修改了什麼檔案,然後找到問題後,根據自己的修改還原回去。這樣避免定位問題時,改了一大堆,卻忘記還原回去。這樣會留下很大的問題。

下面是可以輸出日誌的配置點及其工具,後面有想到的內容會繼續補充。

1、php.ini配置檔案

生產環境配置是:

error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT

display_errors = Off

display_startup_errors = Off

如果著急排查問題,可以複製一份php.ini備份,先把選項開啟,排查完恢復配置

error_reporting = E_ALL

display_errors = On

display_startup_errors = On

對php.ini的修改,需要重啟php-fpm服務。對它的直接修改會影響全域性,如果必要可以不改php.ini,修改PHP框架入口。現在開發系統都用框架,入口檔案就一個,修改很方便,一般都是index.php。

在入口檔案開頭,加入:

error_reporting(-1); // reports all errors ini_set(“display_errors”, “1”); // shows all errors ini_set(“log_errors”, 1); ini_set(“error_log”, “/tmp/php-error.log”);

這樣就覆蓋了php.ini的配置。

此外,還有一個注意事項,PHP如果開啟了OPcache,它是有重新整理時間的。比如預設設定成60秒重新整理,意味著你對PHP檔案的修改,不會立刻生效。在一些時刻可能會誤導你,以為修改沒有產生任何作用。

2、Nginx的配置

Nginx系統的配置檔案很靈活。錯誤輸出可以全域性配置,也可以單獨根據需要配置。全域性檔案一般在安裝目錄的conf/nginx.conf

具體語法這裡不講,可以去查詢。這個日誌指令可以放在開始的地方:

error_log /home/wwwlogs/error_nginx.log crit;

把crit改成error。不過不建議在這裡更改。nginx有配置檔案的include功能,建議單獨在需要開啟日誌的server配置中新增這行指令,改成error。

3、使用xdebug和strace

xdebug是非常強大的除錯工具。我喜歡用PHP,估計有一半原因是因為有它,斷點除錯易如反掌。

使用指令:pecl install xdebug 即可自動下載編譯安裝。但是需要修改php.ini,新增xdebug模組後,還要重啟php-fpm服務。

如果還找不到問題根源,就要拿起重量級武器了:strace,這是一個強大的除錯工具,它可以追蹤程式的系統呼叫、檔案讀寫,對於追查問題很有幫助。

使用如下指令開啟對php-fpm執行過程的追蹤:

strace $(pidof “php-fpm” | sed ‘s/\([0-9]*\)/-p \1/g’) -o phpstrace

不過追蹤時間不能長,因為輸出的日誌量可能非常大,不利於分析。建議只追蹤一次出問題的呼叫,就關閉,然後開啟phpstrace日誌檔案分析。

經過分析,發現是一個模組的程式碼,語法出錯了。可是,此程式碼從未修改過,前面也執行的十分正常。馬上想起來,此伺服器的PHP執行環境是7.0,前面的伺服器環境是7.1,所以語法出現相容性問題。百密一疏。把PHP執行環境升級到7.1最新版本,解決問題。

作者部落格

相關文章