在 Debian 中让定时器等待网络再执行
推荐做法
- 使用 systemd.timer + systemd.service 组合,并在服务单元中加入网络就绪依赖,确保任务只在网络可用时运行。
- 在服务单元中设置:
- Unit 段:使用 After=network-online.target 与 Wants=network-online.target,表示“等到网络在线后再启动服务”;不要用仅表示“网络栈已启动”的 network.target,它不保证链路真正可用。
- Timer 段:按需选择 OnCalendar=(日历时间)、OnBootSec=(开机后延迟)、OnUnitActiveSec=(上次激活后间隔)等;需要“关机错过则补执行”时加 Persistent=true。
- 服务类型:短任务用 Type=oneshot;长时间运行用 Type=simple 并配合 Restart=on-failure 等策略。
完整示例
- 服务单元:/etc/systemd/system/net-sync.service
[Unit]
Description=Network Sync Job
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/net-sync.sh
User=backup
Group=backup
StandardOutput=journal
StandardError=journal
TimeoutSec=300
- 定时器单元:/etc/systemd/system/net-sync.timer
[Unit]
Description=Run network sync hourly after boot
[Timer]
OnBootSec=5min
OnUnitActiveSec=1h
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now net-sync.timer
- 说明:上述配置在系统启动后 5 分钟首次执行,之后每隔 1 小时执行一次;若关机期间有触发事件,开机后会自动补执行(Persistent=true)。
调试与验证
systemctl list-timers --all
systemctl status net-sync.timer
journalctl -u net-sync.service -b
journalctl -u net-sync.timer -b
sudo systemctl daemon-reload
sudo systemctl restart net-sync.timer
- 若任务仍过早触发或偶发失败,优先检查是否使用了 network-online.target,并确认网络管理器的“网络在线”判定符合预期(例如等待至少 1 个默认路由/网关与 DNS 可用)。
常见坑与替代方案
- 仅用 cron 或 @reboot 的任务可能在网络就绪前运行,不适合依赖网络的任务;这类场景应改用 systemd 的定时器与服务依赖。
- 不要把 network.target 当成“网络可用”的等价物;请使用 network-online.target 来表达“链路可用”的语义。
- 需要“错过即补执行”时,给 .timer 加上 Persistent=true;需要错峰执行时,可加 RandomizedDelaySec=(例如 5m)。