php.ini 預設 max_execution_time = 30 秒。超時會導致 Fatal error: Maximum execution time of 30 seconds exceeded。
max_execution_time = 300 ; 5 分鐘
<?php
ini_set('max_execution_time', 300); // 300 秒
ini_set('max_execution_time', 0); // 0 = 無限制 (慎用)
// 保存原值,結束前恢復
$original = ini_get('max_execution_time');
ini_set('max_execution_time', 300);
// ... 長時間任務 ...
ini_set('max_execution_time', $original);
?>
set_time_limit()<?php
set_time_limit(300); // 重設為 300 秒
set_time_limit(0); // 無限制
// 累加模式:每次呼叫**重新計時** 300 秒
// 適合迴圈中定期呼叫防止超時
for ($i = 0; $i < 10000; $i++) {
if ($i % 100 === 0) set_time_limit(30);
// 處理資料...
}
?>
max_execution_time = 0 (無限制),ini_set 可能受限於 disable_functions。max_execution_time 搭配 zend.max_execution_timing (PHP 7.4+) 或使用 pcntl_alarm。fastcgi_read_timeout、Apache Timeout、Proxy proxy_read_timeout 可能先於 PHP 觸發 504 Gateway Timeout。不要在 HTTP 請求中直接執行超過 30 秒的任務。應採用非同步佇列:
- HTTP 請求快速寫入任務到 Redis/RabbitMQ/Database 佇列,立即返回「已接收」。
- Worker 進程 (Supervisor 管理) 從佇列取出任務執行,無時間限制。
- 前端輪詢/WebSocket 獲取進度/結果。
<?php
// 顯示剩餘時間
echo '剩餘秒數: ' . (ini_get('max_execution_time') - (time() - $_SERVER['REQUEST_TIME']));
// 註冊關閉函數記錄超時
register_shutdown_function(function() {
$error = error_get_last();
if ($error && $error['type'] === E_ERROR && strpos($error['message'], 'Maximum execution time') !== false) {
error_log('SCRIPT TIMEOUT: ' . json_encode($error));
}
});
?>