timer 与 cron
两者都能定时执行任务,但设计出发点不同:systemd timer 把定时任务纳入服务管理体系,天然具备依赖声明、错过补跑、日志统一与资源控制能力;cron 胜在轻量、语法人尽皆知、跨发行版一致。新服务与有依赖关系的任务优先用 timer,容器内或简单周期任务继续用 cron 也完全合理,两者可以长期共存。
基本信息
| 用途 | 定时任务的技术选型与迁移判断 |
|---|---|
| timer 组成 | 一对单元文件:xxx.timer 定义何时触发,xxx.service 定义做什么 |
| 校验工具 | systemd-analyze calendar 可解析并验证日历表达式 |
| 查看入口 | systemctl list-timers 显示下次触发时间,crontab -l 看用户任务 |
典型使用场景
- 需要等挂载或网络就绪:用 After 与 Requires 声明依赖,不必在脚本里写等待
- 要求错过就补跑:机器在计划时间处于关机状态时,timer 可以在开机后补跑
- 需要错峰:给成百上千台机器加随机延迟,避免整点同时打爆后端
- 需要限资源:给任务设置内存与 CPU 上限,防止批处理压垮机器
- 日志统一:任务输出直接进 journal,查询与轮转交给系统统一处理
最小的 timer 组合
最小的 timer 组合
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily backup trigger
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
# /etc/systemd/system/backup.service
[Unit]
Description=Daily backup
[Service]
Type=oneshot
ExecStart=/opt/scripts/mysql-backup.sh启用与验证
启用与验证
systemd-analyze calendar '*-*-* 02:30:00' # 先验证表达式解析与下次触发时间
systemd-analyze calendar 'Mon..Fri 09:00' # 支持区间与列表写法
systemctl daemon-reload
systemctl enable --now backup.timer # 注意启用的是 timer 不是 service
systemctl list-timers --all | head # 看下次触发与上次结果
journalctl -u backup.service -n 30 # 任务输出都在这能力对照
| 能力 | cron | systemd timer |
|---|---|---|
| 最小粒度 | 1 分钟 | 秒级 |
| 错过是否补跑 | 默认不补,anacron 只覆盖天级 | Persistent=true 可在下次启动补跑 |
| 错峰抖动 | 需在脚本里自己打散 | RandomizedDelaySec 直接支持 |
| 依赖声明 | 脚本内自行等待 | After、Requires、Wants 声明式表达 |
| 日志去向 | 邮件或自行重定向 | journal 统一收集 |
| 资源限制 | 需要外层工具 | 可复用单元里的资源控制指令 |
| 管理入口 | crontab -e | systemctl 与 list-timers |
迁移不必一刀切:先从「有依赖关系」「需要补跑」「需要限资源」这三类任务开始,收益最明显、风险也最低。其余任务留在 cron 里完全没有问题。
启用时容易漏掉的后半句:systemctl enable --now 的对象必须是 timer。只启用 service 不会创建定时触发,重启后任务就再也不跑了。