首页 / 内容指南 / 当前文章

systemd Timer 的 OnCalendar、OnBootSec、OnUnitActiveSec、Persistent、AccuracySec 和 RandomizedDelaySec 有什么区别?

发布于 2026-08-26 · Content Fleet 编辑部

systemd Timer 的 OnCalendar、OnBootSec、OnUnitActiveSec、Persistent、AccuracySec 和 RandomizedDelaySec 有什么区别?

核心差异速查

设计前先确定需求是“每天九点”“开机十五分钟后”还是“上次成功运行后一小时”,三者并不等价。

Timer Unit 做了什么

.timer unit 在满足时间条件时激活另一个 unit,默认通常是同名 .service。timer 本身不执行备份、清理或脚本,真正工作由被触发 service 完成。

这种分离让调度状态、服务退出码、日志和资源限制分别可观察,也方便手动单独启动 service 测试。

默认触发哪个 Service

backup.timer 默认激活 backup.service。若需触发不同 unit,可在 [Timer] 中设置 Unit=。目标可以是可激活 unit,但常见仍是 oneshot service。

文件名与 Unit 指向错误会导致 timer 正常等待却触发了意外对象,应通过 systemctl catsystemctl show 核实实际加载配置。

OnCalendar 是什么

OnCalendar 使用 systemd 的 calendar event 表达式,按实时时钟触发,例如每日固定时间、工作日或每月特定日期。它适合与人类日历和时区对应的计划。

它受系统时间、时区和夏令时变化影响,与 monotonic timer 的“经过多少时间”不同。

Calendar表达式如何验证

使用 systemd-analyze calendar '表达式' 可以解析表达式并显示下一次触发时间。不要仅凭肉眼猜测 Mon..Fri、日期范围或时区语义。

部署前至少检查多个下一次触发点,覆盖月末、闰日和夏令时切换区间。

OnCalendar=daily 是否精确午夜

daily 对应日历上的每日事件,但实际激活还受 AccuracySec、RandomizedDelaySec、系统负载和服务管理器调度影响。它不是严格实时调度保证。

若业务要求金融级截止,应有任务自身的幂等、迟到检测与补偿,不能只依赖 timer 一次触发。

OnBootSec 是什么

OnBootSec 从系统启动后的单调时间计时,例如开机15分钟后运行。它适合避免服务在启动风暴中立刻执行,或完成一次启动后初始化。

若 timer 在 OnBootSec 指定时点之后才被激活,具体可能立即触发,需结合官方 timer 语义和当前版本测试。

OnStartupSec 是什么

OnStartupSec 从 systemd service manager 启动时计时。对系统manager,它通常与开机接近;对用户manager,用户会话或manager启动时间可能明显晚于系统boot。

因此用户timer需要区分OnBootSec与OnStartupSec,不应假定二者总是相同。

OnActiveSec 是什么

OnActiveSec 从 timer unit 自身被激活时开始计时。每次手动restart timer都会重置这一基准,适合“启用后延迟多久首次运行”。

它与OnBootSec的基准不同:后者由boot决定,前者由timer activation决定。

OnUnitActiveSec 是什么

OnUnitActiveSec 从被触发unit上次激活时开始计算下一次触发,常用于周期运行。若service执行时间较长,它以激活时间而非完成时间为起点。

这意味着“每小时启动一次”与“每次完成后休息一小时”不同,后者更接近OnUnitInactiveSec。

OnUnitInactiveSec 是什么

OnUnitInactiveSec 从目标unit上次变为inactive开始计时,适合任务完成后等待固定间隔再运行。长任务不会挤占休息间隔。

若service保持active,例如oneshot配合RemainAfterExit,timer可能无法获得预期inactive基准,必须核对service Type和状态。

Monotonic Timer是什么

OnBootSec、OnStartupSec、OnActiveSec、OnUnitActiveSec和OnUnitInactiveSec属于基于单调时钟的表达。它们关注经过时间,通常不受手工调整墙上时钟影响。

系统挂起期间是否继续计时与WakeSystem等配置和时钟选择有关,应按systemd.timer当前手册验证。

多个触发条件如何组合

同一timer可以包含多个OnCalendar或monotonic表达式,只要任一个条件到期就可能触发目标unit。它们通常是“或”关系,不是必须同时满足。

如果多个事件在service仍active时到达,systemd不会并行启动同一个unit的新实例;可能看起来像某次触发被合并。

Persistent 是什么

Persistent=true 会为timer保存上次触发时间,在再次激活时检查OnCalendar事件是否在停机期间错过;若错过,会触发一次补跑。官方文档把它描述为类似anacron的行为。

它主要作用于OnCalendar,不会把关机期间每一个错过周期逐次重放。

Persistent补跑多少次

如果机器关机一周、每日任务错过七次,Persistent通常在恢复时触发一次,而不是连续执行七遍。任务需要根据自身检查点处理累计遗漏的数据。

若业务确实要求按每个时间片补齐,应由应用维护watermark和幂等队列,而非依赖timer生成历史实例。

Persistent的时间戳保存在哪里

systemd会保存与timer相关的时间戳状态。删除状态、使用临时系统或权限/目录异常可能改变补跑判断。不要把Persistent当成跨灾难恢复数据库。

备份任务本身应保存独立成功检查点并验证产物,不能仅相信timer曾触发。

AccuracySec 是什么

AccuracySec 指定timer可以在计划时点之后多大的精度窗口内触发。systemd在窗口中选择主机相关、稳定的位置,以便合并本机timer唤醒并节能。

它不是“每次完全随机延迟”,也不是允许任务提前于计划时点执行。

AccuracySec 为什么让任务不准点

默认AccuracySec通常不是零,因此OnCalendar写09:00并不保证进程恰在09:00:00启动。需要更高精度时可降低它,但仍受timer slack和系统调度影响。

把它设得极小会增加CPU唤醒和能耗,应只在业务确有需要时使用。

RandomizedDelaySec 是什么

RandomizedDelaySec 在原计算触发点上增加0到指定时长的随机延迟,用于分散多台机器或多个任务同时启动造成的惊群。

例如所有主机每日零点备份,可增加随机窗口避免同时压垮对象存储,但必须保证最晚完成时间仍满足业务目标。

AccuracySec 与 RandomizedDelaySec 的区别

AccuracySec用于timer精度与本机唤醒合并,位置是稳定且会与其他timer同步优化;RandomizedDelaySec旨在把触发分散到随机窗口。想做fleet级错峰时主要考虑后者。

二者可同时影响最终时间。排查时不能只看OnCalendar文本。

FixedRandomDelay 是什么

较新systemd版本支持FixedRandomDelay,使RandomizedDelaySec选择的随机偏移在特定机器、用户和timer之间更稳定。它有助于让同一timer每次落在相似偏移,同时不同机器分散。

该指令的可用性取决于systemd版本,部署跨发行版前必须检查man page和systemd --version

RandomizedOffsetSec 是什么

新版本还可能提供用于日历timer的随机偏移语义,与RandomizedDelaySec在重算和稳定性上不同。因为版本差异较大,不应从新手册直接复制到旧系统。

先用systemd-analyze verify验证目标机实际支持的指令。

WakeSystem 是什么

WakeSystem=true 可让timer在硬件和系统支持时从suspend唤醒机器。它不是从完全关机状态自动开机的通用机制。

启用会改变电源行为,应评估笔记本电量、机房策略和BIOS/内核能力。

RemainAfterElapse 是什么

timer触发后默认可保持loaded和active状态。RemainAfterElapse配置会影响没有下一次触发时是否仍保持,进而影响再次start的行为和依赖关系。

一次性timer重复测试前应查看状态,并按需stop再start或重置配置。

timer与service失败的关系

service执行失败不会自动让timer永远失败。timer仍可能在下一时点再次激活service,但启动限速、unit状态和依赖可能影响后续运行。

应单独监控service退出码和timer next elapse。只看timer是active不能证明上一次任务成功。

为什么任务没有重叠执行

systemd不会在同一service unit已active时再次创建并发实例。若timer间隔短于任务时长,新触发不会生成第二个同名service进程。

需要并行实例时应设计模板unit和唯一instance,而不是试图绕过unit状态机;并发还需数据锁和资源控制。

如何安装timer

通常在timer的[Install]中使用WantedBy=timers.target,再执行systemctl enable --now name.timer。enable建立开机依赖,--now同时启动当前timer。

只start不会保证下次开机启用;只enable也不会必然立即启动,这与service unit一致。

修改后为什么要daemon-reload

编辑unit文件后,systemd manager不会自动把磁盘变化当成已加载配置。需要systemctl daemon-reload,再restart相应timer以采用新触发计划。

先用systemd-analyze verify发现语法和引用问题,再reload可降低生产误操作。

systemctl list-timers怎么看

systemctl list-timers显示已加载timer的下次和上次触发信息以及对应unit。使用--all可查看更多未活动timer,具体列随版本变化。

NEXT是计算后的实际计划,不应只查看unit文件猜测。若为空,可能没有下一事件或timer未正确激活。

如何查看实际生效配置

systemctl cat name.timer显示vendor文件和drop-in,systemctl show name.timer提供运行时属性,systemctl status显示状态与近期日志。它们比只读/etc中的一个文件可靠。

同名unit可能来自/usr/lib/etc或generator,优先级和drop-in会改变最终值。

如何测试而不等到明天

先用systemd-analyze calendar验证表达式,再在隔离环境临时改为短间隔,启动timer并观察list-timers、service状态和journal。测试结束恢复正式配置并验证reload。

不要在生产备份service上随意缩短到秒级,避免并发I/O或重复副作用。

时区与夏令时风险

OnCalendar依据real-time clock和时区。夏令时切换可能出现不存在或重复的本地时间,系统时间校正也会改变下一事件。

跨时区业务可显式使用UTC或经过验证的时区表达,任务还应通过业务日期幂等,防止重复或遗漏。

与cron的主要差异

systemd timer把调度、依赖、服务沙箱、日志、资源限制和状态查询整合到unit模型,并提供monotonic timer与Persistent补跑。cron表达更简洁,但生命周期集成较少。

迁移不能只机械翻译时间表达式,还要决定service用户、工作目录、环境、超时和失败告警。

可靠任务的设计清单

明确时间基准与时区,选择OnCalendar或monotonic指令;决定是否补跑和是否错峰;为service设置明确用户、超时、资源限制和退出码;让业务操作幂等并持久保存成功watermark。

最后监控timer是否有next elapse、service最近结果、产物新鲜度和任务持续时间。

FAQ:Persistent会补跑OnBootSec吗?

Persistent的补跑语义针对OnCalendar事件。OnBootSec以本次开机为基准,不是对上次关机期间的周期逐次补跑。

FAQ:OnUnitActiveSec=1h是否每个整点运行?

不是。它从目标unit上次激活时间计时;需要整点或固定日历时刻应使用OnCalendar。

FAQ:AccuracySec=1h能让多台服务器随机错峰吗?

它主要用于精度窗口和唤醒合并,不是fleet级随机分散工具。错峰应评估RandomizedDelaySec等指令。

FAQ:timer是active是否表示任务成功?

不表示。active通常说明timer正在等待下一事件,必须查看被触发service的退出状态、journal和业务产物。

FAQ:机器关机七天,daily Persistent会执行七次吗?

通常只在恢复时触发一次补跑。需要逐日补齐的任务必须根据应用自己的日期检查点循环处理。

结论

OnCalendar解决日历时刻,OnBootSec和其他monotonic指令解决相对时间,Persistent解决错过日历事件的一次补跑,AccuracySec负责精度与合并唤醒,RandomizedDelaySec负责分散启动。可靠调度还需要幂等service、版本核验、日志监控和业务检查点,不能只以timer active作为成功证据。

systemd官方资料

1. systemd.timer手册:https://www.freedesktop.org/software/systemd/man/latest/systemd.timer.html

2. systemd.time手册:https://www.freedesktop.org/software/systemd/man/latest/systemd.time.html

3. systemctl手册:https://www.freedesktop.org/software/systemd/man/latest/systemctl.html

4. systemd.service手册:https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html

5. systemd.unit手册:https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html

6. systemd-analyze手册:https://www.freedesktop.org/software/systemd/man/latest/systemd-analyze.html

7. timers.target手册:https://www.freedesktop.org/software/systemd/man/latest/systemd.special.html#timers.target