systemd timer 并非 crontab 升级版,而是以 .timer/.service 配对单元重构调度逻辑,支持日志、依赖、重启等系统级能力;需同名同目录,timer 仅触发 service,后者用绝对路径 ExecStart 和 oneshot 类型;OnCalendar 支持秒级精度与自然语言表达,须显式声明 PATH、HOME、WorkingDirectory 等环境;Persistent=true 可补执行错失任务,所有日志统一由 journalctl 管理。

systemd timer 不是 crontab 的“升级版命令”,而是整套调度逻辑的重构:它用两个配对单元(.timer + .service)替代单行 crontab 条目,天然集成日志、依赖、重启、环境控制等能力,特别适合需要可靠性、可观测性与系统级协同的任务。
必须配对编写:timer 和 service 缺一不可
systemd timer 本身不执行任何命令,只负责在指定时间点“唤醒”同名的 .service 单元。两者必须同名(如 backup.timer → backup.service),且放在同一目录(/etc/systemd/system/ 系统级,或 ~/.config/systemd/user/ 用户级)。
- timer 文件只写触发规则:OnCalendar、OnBootSec、Persistent、RandomizedDelaySec 等
- service 文件定义实际动作:ExecStart 必须用绝对路径;Type 必须设为 oneshot(一次性任务);建议显式声明 Environment、WorkingDirectory、User
- 修改任一文件后,都要运行 systemctl daemon-reload 才能生效
OnCalendar 时间表达式:语义清晰,精度可控
相比 cron 的五段式,OnCalendar 支持自然语言缩写和秒级指定,更易读也更准。关键细节:
- 每天凌晨 2:15 执行:OnCalendar=*-*-* 02:15:00(秒不能省略)
- 每月 1 日、15 日上午 9 点:OnCalendar=*-*-01,15 09:00:00
- 每周一至周五下午 4 点:OnCalendar=Mon..Fri *-*-* 16:00:00
- 避免用 hourly 这类别名——它等价于 *-*-* *:00:00,可能和你预期的“每小时整点”有偏差
- 对时间敏感任务,加上 AccuracySec=1s(默认 60 秒),再配合 RandomizedDelaySec=2min 防集群雪崩
让任务真正可靠:环境、权限与容错不能靠猜
crontab 默认继承用户 shell 环境,而 systemd service 完全不加载 ~/.bashrc 或 /etc/environment。常见静默失败原因都在这里:
- PATH 未声明 → 报 “Command not found”:在 service 中加 Environment="PATH=/usr/local/bin:/usr/bin:/bin"
- 脚本中用了 $HOME 或 ~ → 变量不展开:改用绝对路径,或显式设 Environment="HOME=/root"
- 工作目录不对 → 找不到配置文件或输出路径错误:加上 WorkingDirectory=/opt/myapp
- 任务中途失败导致 timer 停摆:加 RemainAfterExit=yes 和 Restart=on-failure(需搭配 RestartSec)
- 机器关机错过任务?启用 Persistent=true,开机后自动补执行一次
调试与日常管理:用对命令才不抓瞎
所有执行记录都进 journal,不再散落各处:
- 查看所有活跃定时器:systemctl list-timers --all
- 查某次执行是否成功、输出什么:journalctl -u myjob.service -n 50 -o short-precise
- 手动触发一次测试:systemctl start myjob.service(不走 timer,直接跑 service)
- 启用并开机自启:systemctl enable --now myjob.timer
- 停用定时器(service 不会自动停):systemctl disable --now myjob.timer


















