用 systemd Timer 替代 cron:让 Linux 定时任务更可靠
cron 是 Linux 上最常见的定时工具,但它有几个与生俱来的短板:机器关机期间错过的任务不会补跑;任务失败不会自动重试;输出只能靠邮件或重定向;想查上次执行情况,得自己翻日志。systemd Timer 就是为了解决这些问题而生的:它把“什么时候跑”和“跑什么”拆成两个单元文件,再配合 journald 的统一日志,让定时任务变得可观测、可补跑、可依赖。
从一个备份任务说起
假设每天凌晨两点把 /home 打包备份到 /backup。先写 service 单元 /etc/systemd/system/backup.service:
[Unit]
Description=备份 /home 目录
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
再写 timer 单元 /etc/systemd/system/backup.timer:
[Unit]
Description=每天凌晨两点执行备份
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
Unit=backup.service
[Install]
WantedBy=timers.target
执行 systemctl daemon-reload && systemctl enable --now backup.timer,任务就生效了。systemctl list-timers 能看到下一次触发时间,精确到秒。
OnCalendar 怎么写
格式是“星期 年-月-日 时:分:秒”,星号表示任意。每天凌晨两点:*-*-* 02:00:00;每周一早上九点:Mon *-*-* 09:00:00;每 15 分钟一次:*-*-* *:0/15:00;每月 1 号:*-*-01 00:00:00。也可以用相对时间,如 OnBootSec=10min 表示开机 10 分钟后触发。
比 cron 强的四个地方
第一,Persistent=true 会补跑。笔记本合盖、服务器重启期间错过的任务,会在下次开机后尽快补执行一次,cron 错过了就是错过了。
第二,随机延迟。RandomizedDelaySec=10min 让触发时间在窗口内随机偏移,几百台机器同时拉取更新时,不会在同一秒把源站打垮。
第三,日志集中。journalctl -u backup.service 直接看到每次执行的输出和退出码,不用再猜失败原因;配合 OnFailure= 还能在失败时发告警。
第四,依赖管理。service 单元可以声明 After=network-online.target,等网络就绪再跑;AccuracySec=1min 则让系统合并触发时间,省电省唤醒。
排障三板斧
任务没跑,先看 systemctl list-timers --all,确认 timer 是 active 且下次触发时间正确;再看 systemctl status backup.timer,常见问题是只 enable 了 service、忘了 enable timer,或 timer 的 Unit= 指向的 service 名写错了;最后 journalctl -u backup.service -n 50 看日志,多数是脚本权限、环境变量或 PATH 的问题——timer 启动的任务环境变量很少,脚本里尽量写绝对路径。
小结
cron 胜在简单,五分钟能上手;但当任务开始重要——备份、巡检、数据同步——systemd Timer 的补跑、日志和依赖管理会让你睡得更安稳。迁移成本也很低:一个 .service 加一个 .timer,两条命令就能跑起来。下次要加定时任务时,不妨直接写 Timer。
- 点赞
- 收藏
- 关注作者
评论(0)