PHP 本身無內建定時器,常見兩種實現:**腳本內長運行循環** 與 **系統級 Crontab**。本文對比原理、優缺點、適用場景,並給出生產級建議。
<?php
ignore_user_abort(true); // 瀏覽器關閉也繼續執行
set_time_limit(0); // 移除 30s 執行限制
$interval = 24 * 3600; // 每天執行一次
$nextRun = time() + $interval;
while (true) {
// 精確對齊間隔(避免執行時間漂移)
$sleep = $nextRun - time();
if ($sleep > 0) sleep($sleep);
// 業務邏輯
try {
$pdo->exec("UPDATE blog SET updated_at = NOW()");
// 記錄執行日誌
error_log("[" . date('c') . "] Cron job executed.");
} catch (Throwable $e) {
error_log("[" . date('c') . "] Cron error: " . $e->getMessage());
}
$nextRun += $interval; // 下次執行時間
}
# /etc/crontab 或 crontab -e (www-data 用戶)
# 每天凌晨 3:00 執行
0 3 * * * /usr/bin/php /var/www/html/cron/daily_update.php >> /var/log/cron/daily.log 2>&1
# 每分鐘檢查隊列
* * * * * /usr/bin/php /var/www/html/cron/queue_worker.php >> /var/log/cron/queue.log 2>&1
| 維度 | 腳本循環 | 系統 Crontab |
|---|---|---|
| 可靠性 | 低:進程掛掉/重啟/部署即停止,無自動恢復 | 高:系統服務保活,掛掉自動重啟,開機自啟 |
| 精確度 | 受 sleep/執行時間漂移影響 | 分鐘級精確,系統時鐘驅動 |
| 資源佔用 | 常駐一個 PHP 進程佔用內存 | 按需啟動,執行完釋放 |
| 日誌/監控 | 需自建 | 系統日誌 + 重定向極簡 |
| 併發控制 | 需自行實現鎖防止重疊 | 天然串行(同一命令不並發) |
| 部署/版本控制 | 代碼內耦合邏輯 | 命令與代碼分離,CI/CD 友好 |
| 適用場景 | 極簡項目、無系統權限、需亞秒級高頻輪詢 | **所有生產環境定時任務首選** |
SIGTERM 信號,完成當前任務後退出:pcntl_signal(SIGTERM, fn() => $shutdown = true);。flock($fp = fopen('/tmp/cron.lock', 'w'), LOCK_EX | LOCK_NB) 防止多實例。將「定時觸發」與「具體執行」解耦:
LPUSH queue:jobs '{"job":"daily_report"}')。php worker.php queue:jobs),可水平擴展、失敗重試、優先級調度。**結論**:能用 Crontab 就不用循環;能用隊列就不用硬編碼邏輯。架構分層,才能應對業務增長。