systemd计时器需配对编写同名.timer和.service单元文件,.timer定义触发规则如OnCalendar,.service用绝对路径ExecStart并设Type=oneshot;必须显式声明环境、路径与工作目录,启用后须重载、enable--now并用list-timers和journalctl验证。

Systemd 计时器不是 cron 的直接替代命令,而是用一对单元文件(.timer + .service)重构整个调度逻辑。它不读 crontab,不继承 shell 环境,也不解析管道或变量,必须显式声明路径、环境和工作目录,否则大概率静默失败。
必须配对编写两个同名单元文件
缺一不可,且命名一致、存放位置一致(如 /etc/systemd/system/backup.timer 对应 /etc/systemd/system/backup.service):
- .timer 文件只写触发规则:OnCalendar、OnBootSec、Persistent、AccuracySec 等;不能写命令
-
.service 文件只写执行动作:ExecStart 必须是绝对路径(如
/usr/local/bin/backup.sh,不能写backup.sh或sh backup.sh) - Type 必须设为
oneshot;建议加上RemainAfterExit=yes避免因退出码非 0 导致 timer 停止
时间表达式要写准,别信模糊词
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,不是“每小时整点”,而是“每小时第 0 分第 0 秒”,若系统负载高可能延迟 - 需要秒级精度?加
AccuracySec=1s;防集群雪崩?加RandomizedDelaySec=2min
环境、路径、权限必须手动补全
cron 默认加载 ~/.bashrc 和 /etc/environment;systemd 完全不走这套——所有依赖都要显式写进 .service:
- PATH 没声明 → 报
Command not found:加Environment="PATH=/usr/local/bin:/usr/bin:/bin" - 脚本里用了
$HOME或~→ 变量不展开:改用绝对路径,或加Environment="HOME=/root" - 相对路径报错(如找不到 config.json)→ 加
WorkingDirectory=/opt/myapp - 不要在 ExecStart 里写
sh -c "echo $USER | mail":管道、重定向、变量展开均不生效;逻辑应封装进独立脚本
启用后务必检查三件事
写完文件只是开始,以下步骤跳过一个就可能白忙:
- 重载配置:
sudo systemctl daemon-reload(系统级)或systemctl --user daemon-reload(用户级) - 启用并启动:
sudo systemctl enable --now myjob.timer - 验证状态:
systemctl list-timers --all | grep myjob看是否列出、下次触发时间是否合理;查日志必须看 service 单元:journalctl -u myjob.service -n 30 -f


















