首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 捕獲腳本執行超時 (max_execution_time) 的唯一可靠方法:register_shutdown_function

     編輯:PHP 相關知識

set_error_handler() 無法捕獲 E_ERROR 等致命錯誤,超時屬於致命錯誤。唯一可靠方案是註冊關閉函數,在腳本終止前檢查 error_get_last()。

核心代碼

ini_set('max_execution_time', 1); // 1 秒超時,演示用

function shutdown() {
    $error = error_get_last();
    if ($error && in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE])) {
        // 記錄日誌、發送告警、優雅降級
        error_log("FATAL: {$error['message']} in {$error['file']}:{$error['line']}");
        // 可選:發送郵件/Slack/釘釘通知
    }
}
register_shutdown_function('shutdown');

// 模擬長時間運行
while (true) {
    // sleep() 不計入 max_execution_time
    // usleep() 計入
    usleep(100000);
}

關鍵細節

  1. sleep() 不計入執行時間:系統調用掛起進程,CPU 時間不累積。用 usleep() 或真實計算測試。
  2. error_get_last() 只保留最後一個錯誤:若 shutdown 內再觸發錯誤會覆蓋,需立即保存。
  3. 關閉函數運行在獨立作用域:無法訪問主腳本局部變量,需用全局/靜態變量傳遞上下文。
  4. 無法恢復執行:只能做善後 (日誌/通知/降級輸出),不能 return 繼續主流程。

生產級封裝

class FatalErrorHandler {
    public static function register(callable $handler) {
        register_shutdown_function(function () use ($handler) {
            $error = error_get_last();
            if ($error && self::isFatal($error['type'])) {
                $handler($error);
            }
        });
    }

    private static function isFatal(int $type): bool {
        return in_array($type, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE]);
    }
}

// 使用
FatalErrorHandler::register(function ($error) {
    // 發送到 Sentry/日誌中心
    \Log::channel('fatal')->error($error['message'], $error);
});

適用場景

  • 長時間運行的 CLI 命令/隊列消費者
  • 高併發 Web 請求防止白屏無日誌
  • 需對超時做業務補償 (如釋放鎖、回滾狀態)

這是 PHP 運行時層面唯一能「感知」致命錯誤的鉤子,務必在項目啟動階段 (bootstrap) 註冊。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved