
PHP 錯誤排查與日誌判讀
第一步:讓錯誤可見
PHP 的問題排查,八成的時間浪費在「看不到錯誤訊息」。
正式環境的正確設定
display_errors = Off log_errors = On error_log = /var/log/php/error.log
錯誤不顯示在畫面上,但要確實記錄。 兩者都關掉是最糟的情況——出問題時完全沒有線索。
確認日誌真的寫得進去
ls -l /var/log/php/
目錄必須存在,且 PHP 執行身分要有寫入權限。若權限不足,錯誤會靜默消失。
使用 PHP-FPM 時,行程池設定中也可能指定日誌路徑,需一併確認。
白畫面的排查
頁面完全空白,通常是致命錯誤但沒有顯示。依序檢查:
- 看 PHP 錯誤日誌——多數情況答案就在這裡
- 看網頁伺服器的錯誤日誌——若 PHP 的 error_log 未設定,可能寫在這裡
- 暫時開啟顯示錯誤——僅限測試環境
- 檢查是否為記憶體耗盡——日誌中會有 Allowed memory size 相關訊息
- 檢查語法錯誤——用
php -l 檔名逐檔檢查
如果日誌也是空的
- 可能是在 PHP 啟動前就失敗——檢查
display_startup_errors - 可能是 PHP-FPM 崩潰——檢查 FPM 的日誌
- 可能是輸出被緩衝後遺失——檢查是否有
ob_start()但未正確結束
常見錯誤訊息的判讀
Allowed memory size exhausted
記憶體耗盡。常見原因:
- 一次撈取大量資料庫資料——應改為分批處理
- 處理大圖片——影像處理很吃記憶體
- 迴圈中不斷累積陣列
- 無限遞迴
調高 memory_limit 只是治標。 應該找出為什麼需要那麼多記憶體。
Maximum execution time exceeded
執行超時。要注意這個計時不包含等待外部資源的時間,所以實際耗時可能更長。
常見原因:迴圈中重複查詢資料庫、缺少索引導致查詢緩慢、呼叫外部服務無回應。
Call to undefined function
通常是擴充套件未安裝或未載入。用 php -m 確認,並注意命令列與網頁環境可能載入不同的擴充。
Cannot modify header information
在輸出內容之後才嘗試設定標頭或啟動 session。
最常見的原因是檔案開頭或結尾有多餘的空白或換行——特別是 <?php 之前有空行,或檔案結尾的 ?> 後面有換行。
建議:純 PHP 的檔案不要寫結尾的 ?>,可以避免這類問題。
Headers already sent by ... on line N
訊息會直接告訴你是哪個檔案的哪一行先產生了輸出,依此追查即可。
資料庫相關的問題
- 連線失敗——確認主機、帳號、密碼、資料庫名稱,以及資料庫服務是否正常
- Too many connections——連線數超過上限,可能是持久連線累積或未正確關閉
- 查詢緩慢——啟用慢查詢日誌,找出耗時的語句與缺少的索引
- 字元編碼異常——確認連線的字元集設定與資料庫、資料表一致
找出效能瓶頸
簡易的計時
$start = microtime(true);
// 要測量的程式
error_log('耗時: ' . (microtime(true) - $start));
記錄慢速請求
PHP-FPM 可設定記錄執行過久的請求,並附上呼叫堆疊:
request_slowlog_timeout = 5s slowlog = /var/log/php/slow.log
這是找出瓶頸最直接的方法——它會告訴你程式卡在哪一行。
正式的效能分析工具
需要更詳細的分析時,可使用專門的效能剖析擴充。但這類工具本身有開銷,不建議長期在正式環境啟用。
不要在正式環境做的三件事
- 開啟 display_errors——錯誤訊息可能洩漏路徑與結構
- 留下 phpinfo() 頁面——會完整揭露環境資訊,是很常見的資安疏失
- 用 var_dump 或 echo 除錯——會影響使用者看到的畫面,也可能洩漏資料
第二項要特別注意。 除錯時建立的 phpinfo 檔案,事後常常忘記刪除,而檔名多半容易被猜到。
排查的通用順序
- 確認範圍——全站還是特定頁面?所有人還是部分?
- 看錯誤日誌——PHP 與網頁伺服器兩邊都看
- 確認是否為近期變更造成——程式部署、設定調整、版本升級
- 檢查系統資源——磁碟、記憶體、行程數
- 在測試環境重現——正式環境不適合反覆試驗
第三項最有效。 突然出現的問題,幾乎都能對應到某個具體的變更。
建立可追溯的基礎
平常做好這幾件事,出問題時會省下大量時間:
- 錯誤日誌確實記錄且有輪替
- 記錄每次部署與設定變更的時間
- 保留變更前的備份
- 把磁碟用量納入監控——日誌塞爆磁碟是實際會發生的事故
日誌的判讀與維護見Nginx 與 Apache 的疑難排解。
本文的設定與語法以 PHP 8.x 為例,實際的參數、預設值與支援狀態可能因版本與發行版而異。各版本的支援時程請以 PHP 官方公告為準。套用前請先在測試環境驗證,並確實備份原設定檔。