systemd timer 生成

给已有的 service 配一个定时器:选好节奏,生成 .timer 文件和启用命令,不用再背 OnCalendar 的写法。

生成规则

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 会认为它一直在启动中。