systemd timer 生成
给已有的 service 配一个定时器:选好节奏,生成 .timer 文件和启用命令,不用再背 OnCalendar 的写法。
需要注意
- Persistent 只补跑一次:关机期间错过了多个周期,开机后也只触发一次,不会把漏掉的次数补齐。
- 启用的是 backup.timer,不是 backup.service。只 enable service 不会按时间触发。
- OnCalendar 按系统本地时区解释。服务器跑 UTC 时,表达式里的时间要按 UTC 写。
- RandomizedDelaySec=300 会把实际触发时间往后推最多这么多秒,对时间点敏感的任务要设成 0。
- 被触发的 service 建议写 Type=oneshot;如果任务很快结束,再加 RemainAfterExit=no,避免状态一直是 activating。
生成规则
timer 和 service 是两个单元,靠文件名关联:backup.timer 默认触发 backup.service。不同名时要在 [Timer] 里写 Unit=。timer 本身也要 enable,只 enable service 不会按时间跑。
OnCalendar 的格式是 星期 年-月-日 时:分:秒,* 表示任意值,.. 表示范围,/ 表示步长。比如 Mon..Fri *-*-* 09:00:00 是工作日九点,*-*-* *:00/15:00 是每 15 分钟。
AccuracySec 默认 1 分钟,systemd 会把同一窗口内的任务合并唤醒以省电。要精确到秒就设成 1s,代价是更频繁地唤醒 CPU。需要精确到秒的定时任务,cron 反而不如 timer 好控制。
命令要在能拿到完整环境的地方测一遍:systemd 启动的进程没有登录 shell 的 PATH,nvm、虚拟环境、相对路径都容易在这里翻车。已经生成过 service 文件的话,用systemd 服务配置生成对齐工作目录和环境变量。
常见问题
timer 和 cron 怎么选?
已经在用 systemd 的机器上,timer 的好处是能和 service 共享日志、依赖和资源限制,还能补跑关机期间错过的任务(Persistent)。cron 更适合一行就写完的短任务,排查时只能翻邮件或系统日志。
为什么启用了 timer 却不触发?
先确认 service 文件名和 timer 同名,或者 timer 里写了 Unit= 指对。再看 systemctl list-timers 里 NEXT 是不是空的,OnCalendar 写错时 systemd 会在 daemon-reload 时直接报错,不会静默失败。
Persistent 会补跑几次?
只补一次。关机期间错过了十个周期,开机后也只立即执行一次,不会排队补十次。它的用途是别让备份、续期这类任务因为一次关机就整周不跑。
RandomizedDelaySec 有什么用?
把同一时刻的任务打散,避免几百台机器在整点同时请求同一个接口或同一台数据库。代价是触发时间不再精确,对账、开盘这类对时间敏感的任务要设成 0。
OnCalendar 的时间是哪个时区?
系统本地时区。服务器一般跑 UTC,表达式里的 03:30 就是 UTC 凌晨三点半,不是北京时间。要么把服务器时区改对,要么按 UTC 换算后再写。
service 里要写什么类型?
定时任务通常是一次性命令,写 Type=oneshot 并去掉 Restart=always。如果命令会 fork 到后台自己退出,还要加 RemainAfterExit=yes,否则 systemd 会认为它一直在启动中。