VPS systemd定时器不执行怎么办?Calendar、时区、持久化与错过任务逐项排查

把timer触发、service执行和时区补偿拆开验证
发布于
2

VPS上的systemd定时任务没有执行,先不要把问题归结为“cron更可靠”或直接改成每分钟运行。应先确认.timer是否已启用、.service是否被正确触发,再检查日历表达式、时区、错过任务后的补偿、运行账户和脚本环境。定时器负责触发,服务单元负责执行,二者要分开验收。

先看定时器和服务分别处于什么状态

systemctl list-timers --all
systemctl status example.timer --no-pager
systemctl cat example.timer
systemctl status example.service --no-pager
journalctl -b -u example.timer -u example.service --no-pager

example替换成实际单元名。list-timers --all能看到上次触发和下次触发时间,未激活、触发时间为空或服务反复失败时,原因不同。日志中要区分“定时器没有触发”和“定时器触发了但服务退出”两类问题。

确认安装关系:启用的是timer,不是service

常见的单元组合如下:

/etc/systemd/system/example.timer
/etc/systemd/system/example.service

示例配置:

[Unit]
Description=Run example job

[Timer]
OnCalendar=*-*-* 03:20:00
Persistent=true
Unit=example.service

[Install]
WantedBy=timers.target

修改后先检查语法,再启用定时器:

sudo systemd-analyze verify /etc/systemd/system/example.timer /etc/systemd/system/example.service
sudo systemctl daemon-reload
sudo systemctl enable --now example.timer
systemctl is-enabled example.timer
systemctl is-active example.timer

只执行systemctl start example.service不会创建下一次定时触发;只启用service也不会自动启用timer。若单元由软件包或面板生成,应先确认实际路径和drop-in,不要直接修改会被覆盖的文件。

用systemd-analyze验证Calendar表达式

“每天凌晨运行”可能受星期、时区和语法影响。先让systemd解析表达式:

systemd-analyze calendar '*-*-* 03:20:00'
systemd-analyze calendar 'Mon..Fri 09:00'
systemctl show example.timer -p OnCalendar -p NextElapseUSecRealtime -p LastTriggerUSec

输出会给出规范化后的时间和下一次触发点。表达式中的日期、星期和秒数不要靠猜;如果使用OnUnitActiveSecOnBootSec,它们是相对计时,不是固定的墙上时间。

时区是最常见的“没执行”误判

timedatectl
date -Is
systemctl show example.timer -p TimeUSec -p Timezone

服务器常用UTC,而业务人员按北京时间查看日志。先明确任务使用的时区,再比较NextElapse、journal时间和业务记录。修改时区会影响所有依赖系统时间的任务、证书和日志,不应只为一条timer临时改全局设置。

Persistent只补偿错过的时间点,不是无限补跑

Persistent=true会在定时器离线期间错过触发后,于下一次启动时尝试补偿,但它不等于把离线期间的每一次任务全部补跑,也不保证服务一定成功。若任务有重复执行风险,应在服务内部使用幂等键、日期锁或数据库状态记录。

维护后重点看:

journalctl -u example.timer --since '2 hours ago' --no-pager
journalctl -u example.service --since '2 hours ago' --no-pager
systemctl show example.timer -p Persistent -p RandomizedDelayUSec -p AccuracyUSec

RandomizedDelaySecAccuracySec可能让实际执行时间偏离表达式,尤其是批量服务器同时上线时。它们是调度特性,不应被误判成任务丢失。

手动运行成功,定时器仍失败?比较运行环境

交互终端拥有的PATHHOME、工作目录、凭据和代理变量,systemd服务默认不一定具备。服务单元应使用绝对路径、明确的工作目录和必要的EnvironmentFile

[Service]
Type=oneshot
User=backup
WorkingDirectory=/srv/backup
ExecStart=/usr/local/bin/backup-job
EnvironmentFile=-/etc/example/backup.env
TimeoutStartSec=30min

环境文件权限应只允许服务账户或root读取。不要把密码、访问令牌直接写进可读的单元文件、命令行或日志;需要访问外部存储时,应使用受限凭据并记录脱敏结果。

任务重叠和超时:定时器触发了,但新实例没有并行运行

如果上一次oneshot仍在执行,下一次触发可能被合并或跳过,具体行为取决于服务状态和单元关系。检查进程、退出码和执行时长:

systemctl show example.service -p ActiveState -p SubState -p Result -p ExecMainStatus
ps -ef | grep -E '[b]ackup-job'
journalctl -u example.service -o short-iso --no-pager

对不能并发的任务,可在脚本中使用flock或数据库锁,并明确超时后的回滚和告警。不要用无限重试把一个卡死的服务变成永久占用。

改完后怎么做一次可复核的验证

  1. 先手动启动service,确认退出码和输出符合预期。
  2. 用临时的短周期timer验证触发链,再恢复正式日历表达式。
  3. 重启VPS,检查timer是否自动激活、下次触发时间是否存在。
  4. 等待或模拟一个明确的触发窗口,核对timer和service两份日志。
  5. 检查任务产物、文件权限、数据库记录和外部通知,而不是只看服务为inactive。
  6. 记录时区、单元版本、上次触发、失败原因和人工补偿动作。

如果定时任务用于备份,验证的不只是“命令跑过”,还应检查备份文件可读、恢复点和业务数据一致性,可参考VPS备份恢复后的完整性验收。若任务启动依赖挂载、数据库或网络,需结合systemd服务依赖与启动顺序排查确认依赖关系。

常见修复边界

  • 定时器未启用:执行enable --now并确认timers.target。
  • 表达式错误:先用systemd-analyze calendar校验,不靠手算。
  • 时区不一致:统一记录UTC或明确本地时区,不随意修改全局时钟。
  • 错过触发:评估Persistent=true与任务幂等性,必要时人工补偿。
  • 服务失败:修复账户、权限、环境、路径或依赖,别只增加触发频率。
  • 任务重叠:加锁、超时和告警,避免并行写同一份数据。

结论

systemd timer不执行时,最短排查路径是:看list-timers确认触发点,读timer和service日志,验证Calendar与时区,再比较服务运行环境,最后用受控重启和明确触发窗口复核。把定时器和服务拆开观察,通常比反复重启或改成更短周期更快找到真正原因。

常见问题(FAQ)

只启动example.service,为什么下一次定时任务还是没有?
service和timer是两个单元。手动启动service只执行当前任务,不会安排下一次触发;应启用并激活example.timer,再用list-timers确认下次时间。
Persistent=true会把错过的每次任务全部补跑吗?
不会。它只会在定时器离线后尝试补偿错过的触发,不等于按离线期间的次数全部补跑;任务仍需具备幂等性和重复执行保护。
定时器显示下一次时间,但任务仍没有结果,先查哪里?
先看timer日志确认是否触发,再看对应service的退出码、运行账户、PATH、工作目录、凭据和依赖。定时器正常不代表服务执行成功。
服务器使用UTC会影响OnCalendar吗?
会影响你对触发时间的判断。先用timedatectl、NextElapse和日志确认实际时区,不要为了单条任务随意修改全局时钟。

本文由作者原创/授权发布于极跃圈(jiyueip.com)未经许可,禁止转载。题图来自Unsplash,基于CC0协议。

声明:极跃圈(JIYUEIP.com)内网友所发表的所有内容及言论仅代表其本人,并不反映任何极跃圈(JIYUEIP.com)之意见及观点。

0 讨论
热门最新
总结
暂无总结
0 / 600