許多初學者嘗試在 PHP 腳本中用 sleep() 或 while(true) 實現定時任務,這是錯誤的。PHP 設計為「請求-響應」短生命週期模型,長時間運行會佔用 Worker 進程、洩漏記憶體、阻塞並發。
// 前端 JS(不推薦用於生產)
setInterval(function() {
$.post('task.php', {data}, function(res) {
if (res.code === 1) $('body').append(res.msg + '<br>');
}, 'json');
}, 1000 * 60 * 60 * 10); // 10 小時
缺點:頁面關閉即停止;佔用瀏覽器資源;無法保證執行;安全性差(暴露執行入口)。
| 方案 | 適用場景 | 優點 |
|---|---|---|
Linux crontab + PHP CLI | 分鐘級、小時級任務 | 原生、零依賴、穩定 |
| Systemd Timer | 秒級、需開機自啟 | 精度高、日誌整合 |
| Swoole / Workerman 常駐進程 | 毫秒級、高併發、長連接 | 記憶體常駐、支援異步 |
| 任務隊列 | 異步解耦、重試、分散式 | 可視化、失敗重試、擴展性強 |
# 每天 02:30 執行備份
30 2 * * * /usr/bin/php /var/www/html/cli/backup.php >> /var/log/backup.log 2>&1
<?php
// cli/backup.php
define('APP_PATH', realpath(__DIR__ . '/../'));
require APP_PATH . '/vendor/autoload.php'; // 或框架引導文件
$app = new App\Console\Kernel();
$app->run('backup:daily');
SETNX、文件鎖、flock())。unset、gc_collect_cycles()。set_time_limit(0) 僅用於 CLI,Web 環境嚴禁。php.ini、配置文件。PHP 定時任務絕不應依賴 Web 請求觸發。請使用系統排程器調用 CLI 腳本,或引入成熟的任務隊列框架(Laravel Queue、Symfony Messenger、Hyperf Job),實現可靠、可觀測、可擴展的後台作業體系。