systemd Timer 的 OnCalendar、OnBootSec、OnUnitActiveSec、Persistent、AccuracySec 和 RandomizedDelaySec 有什么区别?
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 cat 和 systemctl 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