Linux 任务调度:cron 与 systemd timer 对比
在 Linux 系统管理中,何时执行任务与执行什么同等重要。
最古老的工具是 cron,而在现代发行版中更常见的是 systemd timer。
本文将比较两者,并整理在不同场景下各自的适用性。
1. 为什么要比较 cron 与 systemd timer?
大多数 Linux 服务器都有类似需求:
- 每天凌晨 3 点执行备份
- 每 5 分钟运行一次健康检查脚本
- 每周日压缩并清理日志
- 启动后 1 分钟仅执行一次的初始化任务
传统上,这些都用 cron 处理,但如今许多发行版已将 systemd 作为默认 init 系统,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 的“计时器单元”。
它根据特定条件(时间、启动后经过时间等)触发另一个 systemd service。
结构总是成对出现:
myjob.service→ 定义实际要执行的任务myjob.timer→ 定义何时触发
3.2 service + timer 基本示例
以每天凌晨 3 点执行备份为例:
(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=等:上一次执行后 X 秒- 依赖处理:可通过
After=、Requires=等表达 - 与 systemd 生态深度集成:
systemctl list-timers、systemctl status等
3.4 systemd timer 的缺点
- 学习曲线比 cron 稍陡(需编写两份文件)
- 仅适用于 systemd 环境(旧系统或非 systemd 环境不支持)
- 对于单行简单任务显得“过度”
4. cron 与 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 单元配置部分可实现 |
| 日志查看 | syslog、邮件等 | journalctl -u <service> |
| 依赖(网络/文件系统) | 无内建支持 | After=、Requires= 等 |
| 与系统集成 | 低 | 高(systemd 全链路) |
| 可移植性 | 较高 | 受 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、极老系统)
6.2 选择 systemd timer 的情况
- 系统已使用 systemd 管理大部分服务
- 需要统一日志、状态查看
- 需要相对时间调度(启动后 X 分钟、上一次执行后 Y 分钟)
- 需要依赖管理(网络、数据库等)
- 在 CI/CD、生产环境中追求一致的可观测性
7. 将现有 cron 迁移到 systemd timer 的技巧
- 列出当前 cron 任务
*
crontab -l* 检查/etc/crontab、/etc/cron.d/* - 拆分为 service + timer
* “执行什么” →
.service* “何时执行” →.timer - 转换时间表达
*
0 3 * * *→OnCalendar=*-*-* 03:00:00**/5 * * * *→OnCalendar=*:0/5 - 测试
*
systemctl start myjob.service手动验证 *systemctl start myjob.timer→systemctl list-timers - 停用旧 cron * 注释或删除旧条目,确认新计时器稳定后再移除
8. 结语:共存亦可
总结:
cron仍是简单、可移植的调度器systemd timer在现代 Linux 环境中提供服务中心化、可观测性、灵活触发等优势
两者并无绝对“正确”答案。若已有 cron 任务无需迁移,保持即可;若正在编写新任务或与服务紧密耦合,优先考虑 systemd timer。

目前没有评论。