DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

重启后不再触发:OnUnitInactiveSec

OnUnitInactiveSec需要当前启动中的停用基准。普通周期任务增加初次触发;严格有效期应保留成功时间,不能靠Persistent恢复停用倒计时。

定时器设置了 OnUnitInactiveSec=24h,服务在关机前执行完毕。开机后,systemctl list-timers 的下一次触发时间却为空,任务也一直不再运行。这时要检查定时器有没有其他启动条件:OnUnitInactiveSec= 需要关联服务的一次停用时刻作为基准,不能直接恢复上一次开机期间的这个时刻。

它适合表达“服务停用后过多久再运行”。如果要求“上次成功下载完成后,最多过 24 小时再检查”,还涉及跨重启保存的业务时间,两个要求不能用同一段配置混同。

给周期任务安排第一次运行

对于允许开机后先运行一次的周期任务,可以把启动触发与停用后的间隔放在同一个定时器中。下面是配置片段,关联的 refresh.service 应是执行完会退出的任务;应将它合并进现有定时器,保留原来的权限、依赖和安装设置:

[Timer]
OnActiveSec=1min
OnUnitInactiveSec=24h
Unit=refresh.service

OnActiveSec= 从定时器被激活时算起,先启动一次服务。此后 OnUnitInactiveSec= 从服务停用时算起,安排下一次运行。它们是独立触发条件,任意一个到期都可能触发服务。

如果实际要求从机器启动时计算第一轮,可按需要使用 OnBootSec=。从启动算起与从定时器激活算起并不相同:开机很久后才激活定时器,前者的时间点可能已经过去。

需要先核对已加载配置与服务状态。例如,定时器是否在当前启动中确实激活,关联的服务是否执行后仍处于 active,以及 drop-in 是否保留了额外的触发条件。RemainAfterExit=yes 会让已退出的 oneshot 保持 active,相关处理可见 oneshot 定时服务执行后不再重复。

修改时不要随手用空赋值“只清掉旧的一个时间”。对这些时间触发项,空赋值会重置已有的触发列表,必须重新明确写出需要保留的条件。

Persistent 不保存这个停用计时基准

给上述配置增加 Persistent=yes,不会让 OnUnitInactiveSec= 在重启后接着上一次的停用时刻倒计时。Persistent= 对 OnCalendar= 定时器生效,用于记录触发时间,并在重新激活时判断停机期间是否错过了日历触发。

固定每天某个时间运行,可以考虑日历计划加持久化补触发。停机期间错过多个日历时间点,也不能把补触发理解成逐个重放所有任务。是否需要补全每一期业务数据,仍由任务自己的处理逻辑决定。

严格的 24 小时有效期需要业务记录

设下载在昨天 02:00 成功完成,今天 08:00 才开机。若开机后只重建一个“从现在起 24 小时”的计时器,下次下载会被推迟到明天 08:00,已经超过原来的有效期。

这类任务应在持久存储中记录最后一次成功完成的时间,并在开机触发时检查数据是否已经到期。到期就刷新;未到期则根据剩余时间安排后续触发。固定日历频率加业务到期检查也可以使用,但检查频率必须满足允许的延迟,不能声称它提供了精确的 24 小时截止点。

记录应在下载和落盘成功后更新,不能用“任务开始过”代替成功。写入时也要避免中途失败留下半个时间文件。机器时钟发生调整、时间戳位于未来,以及上次任务失败,都需要明确处理规则;不要失败一次就把旧数据重新标成有效。

验收应分别覆盖正常运行后的下一次触发,以及完成任务后重启的情况。周期任务要有合理的 next 时间;有效期任务还要证明重启后使用的是上次成功时间,过期数据不会因为重启获得新的 24 小时有效期。