systemd 定时任务错过执行:Persistent 能补什么
机器关机时错过日历任务,可用 Persistent 在恢复后补触发;它不会逐次补齐所有历史任务。给出 service、timer、时区与执行记录的检查方法。
文章目录
计划每天凌晨跑一次检查,服务器那天刚好关机。第二天开机后,任务是否补跑,取决于 timer 的配置。Persistent=true 可以记录日历触发时间,但它不是“把停机期间每一次任务都重放”。
先分清 timer 与 service
timer 决定何时触发,service 决定运行什么。下面用一个只写日志的演示任务,不碰业务数据。保存为 /etc/systemd/system/daily-check.service:
[Unit]
Description=Daily check example
[Service]
Type=oneshot
ExecStart=/usr/bin/logger -t daily-check daily-check-ran
先确认本机 logger 路径确实存在;实际备份脚本应替换为经过单独验证的绝对路径。timer 保存为同目录下的 daily-check.timer:
[Unit]
Description=Run daily check
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target
这是每天 03:00 的日历任务,未明确指定时区时使用系统的本地时区。部署前用 timedatectl 查看系统设置,不要把服务器显示的 UTC 当成北京时间。
校验后再启用
sudo systemd-analyze verify \
/etc/systemd/system/daily-check.service \
/etc/systemd/system/daily-check.timer
systemd-analyze calendar '*-*-* 03:00:00'
sudo systemctl daemon-reload
sudo systemctl enable --now daily-check.timer
systemctl list-timers --all daily-check.timer
语法检查通过只说明单元结构可以解释。正式脚本的权限、环境变量、工作目录和依赖仍需单独检查。timer 的触发也可能受精度窗口、随机延迟或时间同步影响,不能把配置中的秒值当成每次实际启动的保证。
Persistent 的补跑边界
它适用于 OnCalendar 日历 timer。停机期间错过了触发,timer 再次激活时可补一次;错过多天不等于逐日重跑多次。按开机后经过多少时间触发的单调 timer,不是同一套补跑语义。
如果任务正在运行,timer 不会因此启动同一个 service 的另一个实例。一次任务耗时过长,后续触发可能不会形成你想象中的队列。需要处理每一天数据的业务,应让脚本按已处理日期找缺口,并设计幂等,而不是依赖 timer 猜测缺了多少次。
看完成状态,不能只看 timer 活着
systemctl show daily-check.service -p Result -p ExecMainStatus
journalctl -u daily-check.service --since today
timer 处于 active 表示调度器启用,service 的退出状态才帮助判断本次执行。日志中的一行演示消息也不是备份成功证据;真正的备份还要检查产物和恢复能力。
运行时间与补跑行为见 systemd timer 文档源码。任务日志越来越大时,再按 journald 空间检查方法决定保留量。