PHP 腳本執行超時是開發中常見問題:導入大數據、生成報表、視頻轉碼、爬蟲任務等長時間運行場景,若不正確配置超時,會導致進程被強制終止、數據不一致、用戶體驗差。本文系統梳理 PHP 超時機制、配置層級、動態調整與生產環境最佳實踐。
sleep()、流操作阻塞、系統調用等待E_ERROR(致命錯誤),腳本立即終止,無法被 try-catch 捕獲SIGPROF 信號,Windows 使用多媒體計時器| 層級 | 配置方式 | 作用範圍 | 優先級 | 典型場景 |
|---|---|---|---|---|
| 1. php.ini 全局 | max_execution_time = 30 | 所有腳本(CLI 除外) | 最低 | 基礎防護,防止失控腳本佔用資源 |
| 2. Web 服務器覆蓋 | Apache: php_value max_execution_time 60Nginx+FPM: fastcgi_read_timeout 60s | 虛擬主機/場所 | 中 | 項目級差異化配置 |
| 3. 代碼動態調整 | set_time_limit(300) 或 ini_set('max_execution_time', 300) | 當前腳本執行期間 | 最高 | 長任務單獨放寬 |
<?php
// 1. set_time_limit(秒數)
// 特性:每次調用都會「重置」計時器
// 0 = 無限制(慎用!僅 CLI 或受控任務)
set_time_limit(300); // 當前腳本允許 300 秒 CPU 時間
// 2. ini_set('max_execution_time', 秒數)
// 效果等同 set_time_limit,但不重置計時器(僅修改限制值)
ini_set('max_execution_time', '300');
// 3. CLI 模式下默認無限制(max_execution_time = 0)
// Web 模式下默認 30 秒
// 4. 獲取當前設置
echo ini_get('max_execution_time'); // 返回字符串
echo get_cfg_var('max_execution_time'); // 返回 php.ini 原始值
| 誤區 | 真相 | 正確做法 |
|---|---|---|
| set_time_limit 包含睡眠/等待時間 | 不包含 sleep()、DB 等待、curl 等待 | 長任務拆分為多個短任務,或用 CLI + 隊列 |
| Web 超時只受 PHP 控制 | Nginx fastcgi_read_timeout、Apache Timeout、瀏覽器超時均會中斷 | 同步調整 Web 服務器超時 ≥ PHP 超時 |
| ini_set('max_execution_time', 0) 安全 | Web 環境極危險,失控腳本會佔滿 FPM 進程導致服務雪崩 | Web 環境嚴禁 0,最大建議 300 秒 |
| 註冊 shutdown_function 可繼續執行 | 超時後 shutdown 仍會執行,但無法繼續主邏輯 | 關鍵操作用事務/冪等設計,超時後靠重試恢復 |
ob_implicit_flush() + set_time_limit(0)(僅 CLI),邊執行邊輸出進度,避免瀏覽器/代理超時exec('php long_task.php > /dev/null 2>&1 &') 後台運行,主進程即時返回; php.ini 基礎配置
max_execution_time = 30 ; Web 默認 30 秒
max_input_time = 60 ; 輸入解析時間
memory_limit = 256M ; 內存限制
; Nginx + PHP-FPM (www.conf)
request_terminate_timeout = 35s ; FPM 進程硬性終止,略大於 PHP 設置
; Nginx 配置
fastcgi_read_timeout 35s; ; Nginx 等待 FastCGI 響應
; 專項長任務入口(如 /admin/import)
; 僅在該控制器動作中動態調整
set_time_limit(300);
ini_set('memory_limit', '512M');
slowlog (FPM) + request_slowlog_timeout = 10smax_execution_time 觸發次數、FPM 進程數、CPU 使用率總結:Web 環境堅持 30-60 秒基礎超時,長任務走異步隊列(CLI 無限制)。動態調整 set_time_limit 僅作為過渡方案,架構層面應將耗時操作從請求-響應循環中剝離,這才是高併發、高可用 PHP 系統的正確姿勢。