错过的定时任务怎么处理
systemd timer 由 .timer 与 .service 两个单元配合:timer 负责触发时机,service 负责实际执行。当计划时刻机器处于关机或休眠状态,任务默认不会执行;把 Persistent=true 打开后,systemd 会记录上次触发时间,下次开机时立刻补跑一次。这个能力对笔记本、桌面机与夜间可能下电的设备尤其重要,是传统 cron 需要 anacron 配合才有的特性。
基本信息
| 单元组成 | xxx.timer(时机)+ xxx.service(动作) |
|---|---|
| 触发方式 | OnCalendar= 日历触发,OnUnitActiveSec= 间隔触发 |
| 补跑开关 | Persistent=true([Timer] 段) |
| 时间戳文件 | /var/lib/systemd/timers/ 下记录上次触发时间 |
| 查看状态 | systemctl list-timers、systemctl status xxx.timer |
| 权限要求 | 系统级 timer 需 root 写 /etc/systemd/system |
典型使用场景
- 夜间备份任务遇到机器下电,次日开机立即补跑
- 桌面终端每天上报资产信息,用户关机一两天后仍能补上
- 补丁检查类任务需要固定节奏,同时容忍设备异常关机
- 周期性清理缓存与临时目录,避免长期未执行导致目录膨胀
- 替代 cron + anacron 组合,用统一机制管理定时任务
完整配置示例
完整配置示例
# /etc/systemd/system/backup.timer
[Unit]
Description=Nightly backup timer
[Timer]
OnCalendar=daily # 每天零点后触发一次
Persistent=true # 错过则开机后补跑一次
RandomizedDelaySec=10m # 分散触发,避免多机同时开跑
Unit=backup.service # 指定触发的服务单元
[Install]
WantedBy=timers.target
# 对应的 backup.service 里写 ExecStart 与 Nice/IOWeight 等资源约束启用与验证
启用与验证
systemctl daemon-reload # 新增或修改单元后必须重载
systemctl enable --now backup.timer # 启用并立即纳入调度
systemctl list-timers --all | head # 看下次触发时间与上次触发时间
systemctl status backup.timer --no-pager # 看状态与最近一次执行结果
journalctl -u backup.timer -n 20 --no-pager # 触发记录(注意日志可能随重启滚动)
ls -l /var/lib/systemd/timers/ # 里面存的就是补跑判断依据的时间戳文件状态字段读法
| 字段 | 含义 | 判读要点 |
|---|---|---|
| NEXT | 下次触发时刻 | 长期显示 n/a 说明 timer 未启用或条件不成立 |
| LEFT | 距下次触发剩余时间 | 与其他机器一致说明未加随机延迟 |
| LAST | 上次触发时刻 | 明显落后于计划说明任务曾错过 |
| ACTIVE | timer 是否激活 | inactive 时不会触发,需检查 enable 状态 |
| status 的 ExecMainStatus | 上次执行退出码 | 非 0 说明任务本身失败,与补跑无关 |
Persistent=true 只会补跑一次,不会把错过周期逐次补齐:从周一到周五每天关机,周六开机也不会连续执行五次备份,需要逐周期执行的任务要评估 OnUnitActiveSec 或改用业务层面的补数逻辑。
补跑发生在开机后不久,多个重任务叠加会与开机高峰争抢资源,建议给 timer 加 RandomizedDelaySec,给 service 加 Nice 或 IOWeight 等约束。