用 systemd timer 替代 cron:让定时任务可观测、可重试

举报
yd_252225969 发表于 2026/10/27 08:15:22 2026/10/27
【摘要】 cron 失败太安静,本文用一个备份例子讲清 systemd timer 的写法、Persistent 补跑、错峰与重试,以及排查和迁移清单。

每天凌晨三点,备份脚本该跑了,却没有任何动静。等到早上才发现磁盘满了、备份失败了,而 cron 什么也没说。这是我把定时任务从 cron 迁到 systemd timer 的直接原因:cron 很简单,但它太安静了,失败、错过、环境差异都不会主动告诉你。

cron 的三个老毛病

第一,环境太干净。cron 启动的进程只有极少的环境变量,PATH、语言、代理都可能和交互式 shell 不一样,脚本在终端跑得好好的,放进 crontab 就找不到命令。第二,失败不可见。默认情况下,任务的输出只会发邮件,而大多数服务器根本没有配邮件,失败就悄悄过去了。第三,错过不补跑。机器关机或休眠期间到期的任务,cron 不会补跑,备份、清理这类任务漏一次,可能要等第二天才发现。

一个最小的 timer 例子

systemd 把“什么时候跑”和“跑什么”分开写。先写一个 service,描述要执行的命令;再写一个 timer,描述触发时间。

# /etc/systemd/system/backup.service
[Unit]
Description=每日备份

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
WorkingDirectory=/srv/backup
User=backup
Environment=BACKUP_DIR=/srv/backup
Restart=on-failure
RestartSec=60
# /etc/systemd/system/backup.timer
[Unit]
Description=每天 03:00 运行备份

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
RandomizedDelaySec=300

[Install]
WantedBy=timers.target

启用只需要三条命令:

systemctl daemon-reload
systemctl enable --now backup.timer
systemctl list-timers --all

几个值得记住的字段

Persistent=true 是我最看重的一点:机器在触发时间关机,启动后 timer 会把错过的那次补跑一次,备份不再因为一次停机就断档。RandomizedDelaySec=300 则让同一时刻的任务在五分钟内随机错峰,避免几十台机器同时写磁盘、同时请求接口。OnCalendar 的写法比 cron 更直观,Mon *-*-* 09:00:00 就是每周一早上九点,*-*-01 00:00:00 是每月一号,读起来几乎不用查表。

如果任务本身可能偶发失败,可以在 service 里加 Restart=on-failure 和 RestartSec=60,让它先自己重试一次;重试仍然失败,再由人去看日志。不要把重试次数设得太高,备份失败重试三次还不行,大概率是磁盘满了或者权限错了,继续重试只会把日志刷满。

排查终于有地方可查了

timer 最大的好处是可观测。systemctl list-timers 可以看到下一次触发时间、上一次触发时间;journalctl -u backup.service --since today 可以直接看到本次执行的输出和退出码;systemctl status backup.service 能看到它是不是正在跑。出了问题,先看这三条命令,大多数情况五分钟就能定位:是没触发、触发了但命令错了,还是命令跑了但结果不对。

迁移清单与适用边界

迁移时建议按这个顺序做:先把脚本改成绝对路径,不依赖当前目录和交互环境;再把环境变量写进 service 的 Environment,而不是写在脚本里到处找;然后在测试机上手动跑一次 systemctl start backup.service,确认成功后再启用 timer;最后保留一周的 cron 和 timer 对照日志,确认新任务稳定后再删旧的。

timer 并不适合所有场景:需要秒级高频触发、需要跨多台机器协调、需要分布式锁的任务,还是应该用专门的调度系统。单机上每天几次、每周几次的备份、清理、报表、证书检查,用 timer 足够,而且比 cron 更省心。把定时任务从“写完就忘”变成“可查、可重试、可补跑”,是运维里投入很小、回报很稳的一次升级。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。