為什麼用 PHP 寫 Daemon?
- 內建函數豐富(字串、陣列、JSON、資料庫、網路、加密),無需外部工具組合。
shell_exec()/proc_open() 輕鬆調用系統命令,兼具腳本膠水能力與程式語言表達力。
- 團隊統一技術棧,降低維護成本。
Daemon 核心原則
- 無限循環 + 睡眠:
while (true) { ... sleep($interval); } 防止進程退出。
- 禁用 echo,改用日誌:
error_log()、syslog()、Monolog 寫檔案/系統日誌,避免標準輸出導致掛起。
- 每次迴圈重新連接資料庫:防止 MySQL 斷線(
MySQL has gone away)。
- 及時釋放資源:
unset($largeVar)、mysqli_free_result()、imagedestroy(),防記憶體洩漏累積導致 OOM。
- 文件操作前
clearstatcache():避免統計緩存導致判斷錯誤;頻繁開關檔案需 fclose() 釋放 handle,防止耗盡檔案描述符。
資料庫重連範例
function getDb() {
static $mysqli = null;
if ($mysqli instanceof mysqli && $mysqli->ping()) return $mysqli;
if ($mysqli) $mysqli->close();
$mysqli = new mysqli("122.225.96.142", "waihui", "freebsd@fzm", "waihui");
if ($mysqli->errno) {
error_log("DB連線失敗: " . $mysqli->error);
return null;
}
$mysqli->set_charset("utf8mb4");
return $mysqli;
}
// 主循環
while (true) {
$db = getDb();
if ($db) {
// 業務邏輯...
}
sleep(60);
}
進階:Systemd 管理 PHP Daemon
# /etc/systemd/system/php-worker.service
[Unit]
Description=PHP Background Worker
After=network.target mysql.service
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/app
ExecStart=/usr/bin/php /var/www/app/worker.php
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=php-worker
[Install]
WantedBy=multi-user.target
systemctl enable --now php-worker 實現開機自啟、異常重啟、日誌集中。
- 多進程用
systemd 模板 php-worker@.service + systemctl start php-worker@{1..4}。
替代方案對比
| 方案 | 優點 | 缺點 |
| PHP Daemon + Systemd | 語言統一、生態豐富、進程管理標準 | PHP 非事件驅動,高併發需多進程/協程 |
| Swoole/RoadRunner Worker | 協程高併發、常駐記憶體、效能極佳 | 學習曲線、代碼需協程化 |
| Gearman/Redis Queue + CLI Consumer | 解耦、可橫向擴展、多語言消費 | 架構複雜、引入中間件 |
| Bash/Python Cron | 簡單、系統級 | 邏輯複雜時難維護、資料庫操作繁瑣 |
PHP 寫 Daemon 完全可行,關鍵在「重連、釋放、日誌、進程管理」四大紀律。現代專案建議直接上 Swoole/OpenSwoole 或 RoadRunner,獲得原生協程高併發與平滑熱重載能力。
- 上一篇文章: PHP AJAX 分頁顯示數據完整範例
- 下一篇文章: PHP UTF-8 BOM 導致 Header 已送出、Session 失效、圖片損壞的完整解決方案
Copyright ©
程式碼之家 All Rights Reserved