在使用PHP 執行長時間任務時,我們經常會遇到一種情況:用戶關閉瀏覽器或主動斷開請求連接,PHP 腳本就會被中止執行。這對於需要長時間運行或者後端持續處理的腳本來說,是非常致命的。那麼,如何防止用戶斷開連接時腳本被中止呢?答案就是使用ignore_user_abort()函數。
ignore_user_abort()是PHP 提供的一個函數,用於設置當客戶端斷開連接時,腳本是否繼續執行。
ignore_user_abort(true);
當傳入true參數時,即使用戶關閉了瀏覽器,PHP 腳本仍會繼續執行,直到執行完畢或超時/主動退出為止。
處理異步任務
後台隊列處理
定時任務模擬執行
文件生成或大數據導出
需要保持狀態一致性的後台操作
舉個實際的例子,如果你正在開發一個系統備份功能,用戶點擊“開始備份”後,腳本需要運行十幾分鐘才能完成。此時用戶若關閉瀏覽器,默認情況腳本就會中止,備份任務失敗。而通過ignore_user_abort(true) ,即便用戶離開頁面,腳本依舊會在服務器上繼續執行,直至備份完成。
以下是一個典型的長任務處理代碼示例:
<?php
ignore_user_abort(true); // 即使用戶中斷連接也繼續執行
set_time_limit(0); // 取消腳本執行時間限制
file_put_contents('log.txt', "任務開始時間:" . date('Y-m-d H:i:s') . "\n", FILE_APPEND);
// 模擬一個長時間任務
for ($i = 1; $i <= 10; $i++) {
file_put_contents('log.txt', "1。 {$i} 步執行中...\n", FILE_APPEND);
sleep(5); // 模擬每一步耗時
}
file_put_contents('log.txt', "任務完成時間:" . date('Y-m-d H:i:s') . "\n", FILE_APPEND);
?>
你可以通過curl 或Ajax 請求來調用這個腳本,比如:
fetch("https://gitbox.net/run-task.php");
即使用戶在發送請求後關閉瀏覽器,該腳本仍會完整執行。
如果你希望在用戶斷開連接後做一些邏輯處理,比如寫日誌或中止某些行為,可以用connection_aborted()函數來檢測:
if (connection_aborted()) {
file_put_contents('log.txt', "用戶連接已中斷\n", FILE_APPEND);
}
配合ignore_user_abort(true)使用,可以讓你更靈活地處理中斷與不中斷的情況。
使用ignore_user_abort()並不意味著你可以忽視所有異常,中斷可能還來自服務器端(如Nginx、Apache 配置)或PHP 腳本本身(如內存限制)。
推薦同時使用set_time_limit(0)來取消最大執行時間限制。
如果腳本輸出數據到客戶端,盡量在邏輯前就使用ob_start()開啟緩衝,避免輸出行為導致連接問題。
在PHP 中處理長任務時,使用ignore_user_abort(true)是確保腳本不中途被用戶中斷的一種有效方式。它能保證任務在服務端完整執行,提升系統的穩定性和可靠性。對於涉及備份、推送、導出等任務的後台腳本而言,這是一個非常實用的技巧。