用 systemd timer 替代 cron:先想清楚这 7 个注意事项
cron 用起来简单,但它几乎不告诉你任务为什么没跑、跑了多久、是不是跑重了。systemd timer 不是 cron 的简单平替,它把定时任务变成了可查询、可追踪的服务。下面 7 个点,是迁移前最值得先想清楚的。
1. timer 和 service 是两个文件,不要只写一个
timer 只决定何时触发,真正干活的是同名的 service。常见结构是 backup.timer 加 backup.service,timer 里写 OnCalendar,service 里写 ExecStart。只启用 timer 不够,service 也要能被正常拉起;调试时先用 systemctl start backup.service 手动跑一次,确认脚本本身没问题,再去查定时触发。
[Unit]
Description=每天备份
[Timer]
OnCalendar=daily
Persistent=true
Unit=backup.service
[Install]
WantedBy=timers.target
2. OnCalendar 的语义和 cron 不一样
cron 的 0 2 * * * 是每天 2 点,systemd 里对应的写法是 OnCalendar=daily 或者 OnCalendar=--* 02:00:00。注意几点:daily 默认是午夜 00:00,不是 2 点;写 02:00 时要写完整的时间;想每 15 分钟跑一次,可以写 OnCalendar=:0/15。改完先跑 systemd-analyze calendar "-- 02:00:00" 验证下一次触发时间,别凭感觉。
3. 机器关机错过的时间,要不要补跑
cron 错过就错过了,systemd 可以选择补跑。Persistent=true 会在机器恢复后补跑一次错过的任务,适合备份、清理这类晚一点跑也没关系的任务;但对发提醒、拉取实时数据这类任务,补跑旧任务可能反而添乱。先按任务性质决定,再决定要不要开 Persistent。
4. 任务跑重了怎么办
timer 到点就会触发,不管上一轮有没有跑完。如果任务耗时不稳定,要在 service 里想好策略:可以用 Type=oneshot 配合脚本内部的锁,也可以在 timer 里用 RandomizedDelaySec 把多台机器的触发时间错开。不要默认它不会重叠,备份、同步类任务最怕这一点。
5. 环境变量和工作目录不会自动继承
cron 任务的环境很干净,systemd service 也一样:PATH、HOME、当前目录都不能想当然。脚本里要用绝对路径,或者在 service 里显式写 WorkingDirectory、Environment、EnvironmentFile。凡是只在交互 shell 里能跑、放到定时任务里就找不到命令的情况,先查这一项。
6. 日志和状态比 cron 好查,要用起来
这是 systemd timer 最大的好处:systemctl list-timers 可以看到下次触发时间、上次触发时间和剩余时间;journalctl -u backup.service 可以只看这个任务的日志。迁移后别再只看脚本自己的日志文件,把 list-timers 和 journalctl 变成例行检查的一部分。
systemctl list-timers --all
systemctl status backup.timer backup.service
journalctl -u backup.service --since "today"
7. 启用、重载、验证要成套做
改完 timer 文件后,标准流程是:systemctl daemon-reload,然后 systemctl enable --now backup.timer,再用 list-timers 确认 NEXT 列是你想要的时间。只改文件不重载,或者只 start 不 enable,重启后任务就丢了,这是迁移时最常见的低级失误。
迁移前的小清单
先手动跑通 service,再定 OnCalendar;决定错过要不要补跑;给耗时任务加防重叠策略;写死绝对路径和工作目录;最后用 list-timers 和 journalctl 验证一次。把这几步走完,systemd timer 才真正比 cron 省心,否则只是把 cron 的坑换了一个地方踩。
- 点赞
- 收藏
- 关注作者
评论(0)