Linux 上的任務排程:cron 與 systemd timer 比較
在 Linux 系統管理中,"何時" 執行任務與"執行什麼" 同樣重要。
最古老的工具是 cron,而在許多現代發行版中則廣泛使用 systemd timer。
本文將比較兩者,並整理在不同情境下應選擇哪一種。
1. 為什麼要比較 cron 與 systemd timer?
大多數 Linux 伺服器都會遇到以下需求。
- 每天凌晨 3 點執行備份
- 每 5 分鐘執行健康檢查腳本
- 每週日壓縮並整理日誌
- 開機後 1 分鐘執行一次初始化工作
傳統上,所有這些都用 cron 處理,但隨著許多發行版將 systemd 作為預設 init 系統,"timer unit (systemd timer)" 也成為強大的替代方案。
2. cron 基本概念
2.1 cron 是什麼?
cron 是一個古老的 Unix/Linux 排程器。
它根據設定的時間/週期執行命令,設定主要透過 crontab 檔案管理。
2.2 cron 設定位置
- 系統全域:
/etc/crontab、/etc/cron.d/ - 使用者:
crontab -e編輯 per-user crontab
例如,設定每天凌晨 3 點執行備份腳本:
0 3 * * * /usr/local/bin/backup.sh
欄位意義如下。
分 時 日 月 週 命令
0 3 * * * /usr/local/bin/backup.sh
2.3 cron 的優點
- 可靠且經過驗證的工具
- 大多數 Unix/Linux 系統共通概念
- 設定語法簡單,範例豐富
- 在 systemd 之前的系統也可使用
2.4 cron 的限制
- 與服務分離,難以追蹤「與哪個服務相關」
- 狀態/日誌確認不方便(散落於 syslog、郵件等)
- 依賴性管理(如需先啟動其他服務)較弱
- 相對時間排程(如「開機後 5 分鐘執行一次」)不直觀
3. systemd timer 基本概念
3.1 systemd timer 是什麼?
systemd timer 是 systemd 的「timer unit」。
它根據特定條件(時間、開機後經過時間等)啟動另一個 systemd service。
結構總是成對出現。
myjob.service→ 真正執行的工作myjob.timer→ 何時執行
3.2 service + timer 基本範例
以每天凌晨 3 點執行備份為例,使用 systemd timer 如下。
(1) 服務單元:/etc/systemd/system/backup.service
[Unit]
Description=Daily backup job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
(2) 時間單元:/etc/systemd/system/backup.timer
[Unit]
Description=Run daily backup at 3:00
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
啟用:
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
3.3 systemd timer 的優點
- 明確與服務關聯:結構清晰,易於辨識
- 日誌管理簡單:
journalctl -u backup.service等查看 - 靈活的觸發條件:
OnCalendar=:類似 cron 的時間表達OnBootSec=:開機後 X 秒OnUnitActiveSec=、OnUnitInactiveSec=等:最後一次執行後的時間- 依賴性處理:可在 service 的
After=、Requires=等設定 - 與 systemd 生態整合:
systemctl list-timers、systemctl status等
3.4 systemd timer 的缺點
- 相較於 cron 學習曲線較陡(需兩個檔案)
- 依賴 systemd(舊系統或非 systemd 環境不支援)
- 對於簡單的一行任務可能顯得「過度」
4. cron vs systemd timer:功能比較
4.1 大圖比較表
| 項目 | cron | systemd timer |
|---|---|---|
| 設定位置 | /etc/crontab、crontab -e |
/etc/systemd/system/*.service/*.timer |
| 執行對象 | 任意命令/腳本 | systemd service |
| 時間表達 | cron 表達式(5 欄) | OnCalendar、OnBootSec 等多種選項 |
| 開機後 X 秒/分/時 | 限制,需額外腳本 | OnBootSec、OnStartupSec 直接支援 |
| 失敗/重試管理 | 需自行實作 | 透過 service unit 設定部分可行 |
| 日誌確認 | syslog、郵件等 | journalctl -u <service> |
| 依賴性(網路/檔系統) | 無 | After=、Requires= 等單元選項 |
| 與系統整合 | 低 | 高(systemd 全域) |
| 可攜性(跨 OS) | 高 | 受 systemd 依賴 |
5. 以範例看差異
5.1 每天凌晨 3 點備份:cron vs timer
cron 版本
0 3 * * * /usr/local/bin/backup.sh
systemd timer 版本
# backup.service
[Unit]
Description=Daily backup job
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
# backup.timer
[Unit]
Description=Run daily backup at 3:00
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
5.2 開機後 5 分鐘執行一次
在 cron 中通常需要 @reboot + sleep 或 rc.local 等技巧。
systemd timer 實作
# init-job.service
[Unit]
Description=Run custom init job after boot
[Service]
Type=oneshot
ExecStart=/usr/local/bin/init-job.sh
# init-job.timer
[Unit]
Description=Run init job 5 minutes after boot
[Timer]
OnBootSec=5min
AccuracySec=1min
[Install]
WantedBy=timers.target
這樣,開機後 5 分鐘會執行一次 init-job.service。
6. 如何選擇?
6.1 仍使用 cron 的情況
- 已有大量 cron 任務且不需要 systemd 整合
- 需要在非 systemd 環境(容器、BSD、舊版 OS)執行
- 只有少量簡單排程
6.2 選擇 systemd timer 的情況
- 系統已使用 systemd 管理大部分服務
- 想在單一地方查看日誌與狀態
- 需要相對時間排程(開機後 X 時間、最後一次執行後 Y 時間)
- 需要依賴性(如網路、資料庫)控制
- 在 CI/CD、製造環境中需要一致的可觀測性
7. 將現有 cron 任務遷移到 systemd timer 的技巧
- 列出現有 cron 任務
*
crontab -l* 檢查/etc/crontab、/etc/cron.d/* - 拆分為「服務 + 時間」
* 「執行什麼」 →
.service* 「何時執行」 →.timer - 轉換時間表達式
*
0 3 * * *→OnCalendar=*-*-* 03:00:00**/5 * * * *→OnCalendar=*:0/5 - 測試
*
systemctl start myjob.service先手動執行 *systemctl start myjob.timer→systemctl list-timers - 停用舊 cron * 新 timer 穩定後,將原 cron 設定註解或刪除
8. 總結:共存亦可
總結來說:
cron仍是簡單且可攜的排程器systemd timer在現代 Linux 環境中提供服務導向、可觀測、靈活觸發的強大功能
兩者並非互斥;已存在的 cron 任務不必全部遷移,僅在需要更高整合度或依賴性控制時考慮使用 systemd timer。

目前沒有評論。