基本實作
<?php
// 1. 忽略使用者中斷(關閉瀏覽器仍繼續執行)
ignore_user_abort(true);
// 2. 移除執行時間限制
set_time_limit(0);
// 3. 設定間隔(秒)
$interval = 30 * 60; // 30 分鐘
// 4. 無限迴圈
while (true) {
// --- 你的業務邏輯 ---
doTask();
// ----------------------
sleep($interval);
}
function doTask(): void
{
// 例如:清理過期快取、發送排程通知、同步第三方資料
error_log("[" . date('c') . "] 排程任務執行");
}
啟動方式
- CLI 模式(推薦):
php /path/to/cron.php > /dev/null 2>&1 &
- Web 觸發:瀏覽器訪問一次即可,但受限於 Web 伺服器超時設定(Nginx/Apache proxy_read_timeout)。
關鍵函式說明
| 函式 | 作用 | 注意事項 |
ignore_user_abort(true) | 客戶端斷線不終止腳本 | CLI 模式預設即為 true,Web 模式必須設定 |
set_time_limit(0) | 移除 max_execution_time 限制 | 受 max_execution_time、max_input_time、Web 伺服器超時多重限制 |
sleep($sec) | 暫停執行 | 不佔用 CPU,但進程常駐佔用記憶體 |
⚠️ 此方案的嚴重缺陷
不建議用於生產環境的長期任務,主要問題:
- 單點故障:進程掛掉、重啟、OOM、伺服器重開機,任務永久停止,無自動恢復機制。
- 記憶體洩漏風險:長期運行的 PHP 進程若有循環引用、未釋放資源,記憶體持續增長導致 OOM。
- 無法並行:單進程循序執行,任務耗時超過間隔會疊加延遲。
- 部署維護困難:程式碼更新需手動重啟進程,無優雅重載機制。
- 可觀測性差:無內建日誌、監控、重試、死信佇列等企業級特性。
✅ 生產級替代方案對比
| 方案 | 適用場景 | 優點 | 缺點 |
| Linux crontab | 分鐘/小時級簡單任務 | 系統級、零依賴、自動重啟、日誌標準 | 最小粒度 1 分鐘、無分散式鎖 |
| systemd timer | 現代 Linux 替代 cron | 精度更高、依賴管理、日誌整合 journalctl | 學習曲線稍高 |
| Supervisor + CLI | 長期運行的 Worker | 進程監控、自動重啟、日誌導向、優雅重載 | 需額外安裝配置 |
| Laravel Scheduler / Symfony Messenger | 框架專案 | 語法優雅、任務鏈、分散式鎖、佇列整合 | 綁定框架 |
| Redis + Lua / Swoole Timer | 高效能、亞秒級 | 記憶體級速度、協程非阻塞、單機萬級 QPS | 技術棧複雜、需 Swoole 擴充 |
| 獨立排程平台 | 企業級、跨語言、分散式 | Web UI、視覺化、多租戶、高可用、審計 | 基建成本高 |
推薦:Supervisor 管理 PHP CLI 長程式
; /etc/supervisor/conf.d/php-worker.conf
[program:php-scheduler]
command=php /var/www/app/scheduler.php
autostart=true
autorestart=true
user=www-data
numprocs=1
redirect_stderr=true
stdout_logfile=/var/log/supervisor/php-scheduler.log
stdout_logfile_maxbytes=10MB
stdout_logfile_backups=5
environment=APP_ENV="production"
總結
ignore_user_abort + sleep 適合臨時測試、一次性腳本、開發環境驗證邏輯。生產環境請務必使用 crontab / systemd / Supervisor / 框架內建排程 / 專業排程平台,確保可靠性、可觀測性與可維護性。