register_shutdown_function() 註冊的函數會在以下情況執行:
exit() 或 die()可重複註冊,依序執行。
<?php
error_reporting(0); // 生產環境建議關閉錯誤顯示,改用日誌
register_shutdown_function('handleShutdown');
function handleShutdown() {
$error = error_get_last();
// 判斷是否為超時錯誤
if ($error && strpos($error['message'], 'Maximum exec') !== false) {
echo 'handle time out';
// 可在此處:記錄日誌、發送告警、清理資源、寫入審計追蹤
}
}
set_time_limit(2); // 設定 2 秒超時
sleep(3); // 故意超時
error_get_last():取得最後發生的錯誤資訊 (型別、訊息、檔案、行號)strpos($error['message'], 'Maximum exec'):超時錯誤訊息特徵字串set_time_limit(2):覆蓋 php.ini 的 max_execution_timefunction handleShutdown() {
$error = error_get_last();
if ($error && in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR])) {
$log = [
'timestamp' => date('c'),
'error_type' => $error['type'],
'message' => $error['message'],
'file' => $error['file'],
'line' => $error['line'],
'memory_peak' => memory_get_peak_usage(true),
'memory_curr' => memory_get_usage(true),
'request_uri' => $_SERVER['REQUEST_URI'] ?? 'CLI',
'request_method' => $_SERVER['REQUEST_METHOD'] ?? 'CLI',
];
error_log(json_encode($log) . "\n", 3, __DIR__ . '/logs/fatal_errors.log');
}
}
| 方案 | 原理 | 優點 | 缺點 |
|---|---|---|---|
| register_shutdown_function | PHP 內核請求結束階段回調 | 無需擴充、捕獲致命錯誤 | 無法捕獲外部阻塞、無法恢復執行 |
| pcntl_alarm + signal | POSIX 信號 | 可中斷阻塞系統調用 | 僅 CLI、需 pcntl 擴充、非 Windows |
| Swoole/Workerman 定時器 | 事件循環管理 | 全非阻塞、精確控制 | 需常駐進程、架構變更大 |
| Nginx proxy_read_timeout | Web Server 層面 | 保護上游服務 | 非 PHP 內部、回傳 504 而非業務邏輯 |
auto_prepend_file 或框架啟動階段統一註冊file_get_contents/cURL