首页/系统/Linux 运维命令速查/场景:把 crontab 迁移成 systemd timer
定时任务与计划50 条

场景:把 crontab 迁移成 systemd timer

迁移五步:盘点任务、写 service、写 timer、启用验证、下线 cron 行;用真实例子把「每日 02:30 备份」完整搬过去。

Linux 运维命令速查系统更新于 2026-10-13

迁移到 timer 是什么

把 crontab 迁移到 systemd timer 换来的是:日志自动进 journal、可以声明依赖顺序与资源限制、按日历时刻精确调度、关机错过的可以补跑。代价是每个任务要写两个单元文件:service 描述做什么,timer 描述什么时候做。迁移路径固定为五步:盘点任务、写 service、写 timer、并存验证、下线 cron,任何一步跳过都会留下重复执行或漏执行的隐患。

基本信息

场景把现有 cron 任务迁移为 systemd timer
产物xx.service 描述做什么,xx.timer 描述什么时候做
关键参数OnCalendar 定时刻、Persistent 补跑、RandomizedDelaySec 错峰
验证工具systemctl list-timers、journalctl -u、systemd-analyze calendar

典型使用场景

  • 需要日志与执行历史:journal 自动记录每次执行的输出与退出码
  • 需要依赖顺序:After=mysql.service、Wants=network-online.target 保证前置条件
  • 需要资源与优先级控制:Nice、IOSchedulingClass、MemoryMax 直接写在单元里
  • 关机错过要补跑:Persistent=true 是 cron 不具备的能力
  • 统一管理:任务定义以文件形式纳入配置管理与代码评审

service 单元

service 单元
# /etc/systemd/system/db-backup.service
[Unit]
Description=Daily DB backup
After=network-online.target mysql.service
Wants=network-online.target

[Service]
Type=oneshot
User=backup
ExecStart=/opt/scripts/db-backup.sh
Nice=10
IOSchedulingClass=idle

timer 单元与启用

timer 单元与启用
# /etc/systemd/system/db-backup.timer
[Unit]
Description=Run db-backup daily

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

[Install]
WantedBy=timers.target

启用验证与下线 cron

启用验证与下线 cron
systemd-analyze calendar '*-*-* 02:30:00'      # 先验证表达式解析出的下次触发时间
sudo systemctl daemon-reload
sudo systemctl enable --now db-backup.timer    # enable 的是 timer,不是 service
systemctl list-timers db-backup.timer --no-pager
sudo systemctl start db-backup.service         # 手动触发一次,不必等定时
journalctl -u db-backup.service --since today --no-pager | tail -n 20
crontab -l > ~/cron.bak && crontab -e          # 验证通过后再删除旧 cron 行

cron 与 timer 等价写法

cron 写法timer 等价说明
30 2 * * *OnCalendar=*-*-* 02:30:00日历表达式定时刻
*/10 * * * *OnCalendar=*:0/10每 10 分钟一次
@rebootOnBootSec=1min开机后触发
错过的执行Persistent=true只补最近一次
并发错峰RandomizedDelaySec=在时间点后加随机延迟
任务型脚本要用 Type=oneshot:默认 simple 会在 fork 后立即认为启动成功,systemctl 状态与实际执行结果脱节。
迁移前先盘点:crontab -l、/etc/crontab、/etc/cron.d、cron.{hourly,daily,weekly,monthly} 以及既有 timer 五处都要看,逐条记录后销账,避免只搬了用户任务表却漏掉系统目录里的任务。
迁移期两套并存会重复执行任务,可先把 cron 行改成 echo skipped 观察一天,确认 timer 正常后再删除。
迁移后日志进 journal,先确认 journald 持久化(/var/log/journal 目录存在),否则重启后执行历史全部丢失。

迁移检查清单

检查项通过标准说明
任务盘点完整各处来源均有记录避免只搬了一部分
表达式可解析分析工具给出下次触发时间启用前先验证
日志可追溯服务有执行记录与退出码确认日志留存已开启
旧任务已下线任务表里不再重复避免两套同时跑
资源限制已声明单元里有对应字段防止与业务争抢
迁移的价值不止是换个调度器:任务写成单元后可以声明依赖顺序、资源上限、失败策略与补跑规则,这些能力在任务表里都做不到;代价是定义变啰嗦,改一次要动两个文件,因此更适合长期运行、需要审计与可追溯的周期性作业。

易错点

  • enable 的对象是 timer 而不是 service:写错会让任务改由启动时机触发,语义完全不同
  • Type 未设 oneshot 时 systemctl 显示成功但脚本仍在跑,脚本失败不能及时反映到单元状态
  • 日志依赖 journald 持久化,未开启时重启后无法追溯,迁移前先确认 /var/log/journal 存在
  • OnCalendar 表达式写错在 enable 时不报错,要到触发时才会在 journal 里看到解析失败,先用 systemd-analyze calendar 验证
  • 迁移时只搬走任务行却留下旧机器继续运行:重复执行会带来重复推送、重复计费或数据覆盖,下线旧任务要有明确的销账动作与时间点

数据来源与参考

  • systemd 官方文档:Timers
  • man 5 systemd.service
  • man 5 systemd.timer

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌