你在开机时启动客户端,单元报告处于活动状态,隧道却不在。自然的结论是服务启动失败,自然的补救是再启动一次。这两种判断错得足够频繁,值得立一条规则:一个正在运行并不断重试的客户端,从外面看和一个坏掉的客户端完全一样。区别在于进程在做什么,而不在于单元的状态。

误解:服务启动了就等于隧道可用

活动单元只能证明进程被拉起来了而且没有退出。它不能证明配置文件已加载、证书已被接受,或对端已经应答。打包好的客户端可以在重试循环里待上好几分钟,而 systemd 只报告成功。状态与行为之间的这道落差,就是全部问题所在。

相反的情况同样常见。进程可能因为读不到密钥而退出,单元随后报告失败状态,却对原因只字不提。这两种状态都要靠日志来分辨。

要读的是那个实例的日志,而不是单元的状态。原因那一行在日志里,不在状态标签里。

误解:重试设置能覆盖所有失败

名称解析和传输重试是两套独立控制,各有各自的默认值。resolv-retry 管的是对远端主机名的重复查询,文档给出的默认值会无限重试下去。connect-retry 设定两次尝试之间的间隔,而 connect-retry-max 可以限制每个远端条目的尝试次数。动手改其中任何一个之前,先看清日志说的是哪个阶段。

这些都不适用于写坏的配置文件、读不出来的私钥或被拒绝的账号。那些需要修正,而一直重试它们的客户端并没有在前进。

对未获批准的证书无休止重试,并不是取消验证的理由。它反而是去读错误信息的理由。

误解:一个启动器就够了,于是再加一个

已经由 NetworkManager 或打包单元管理的连接,不需要再挂第二个启动器。两个进程争抢同一批路由,会产生重复的接口、混乱的日志,以及一条无人看得出原因的反复起落的隧道。第二份通常是因为第一份慢才被当作绕行方案加上的。

先确定隧道归哪个组件所有,再添加任何东西。然后移除另一个启动器,而不是把它禁用掉再指望没事。

所有者还决定了重试和凭据从哪里来,所以这个决定要排在一切调优之前。所有权之所以排在最前,正是这个原因。

真正需要排序的是什么

排序可以等一个配置好的地址,而它保证的也只有这一点。network-online.target 会把激活推迟到管理器认为网络就绪为止,而就绪的定义取决于管理器。它对 VPN 主机名能否解析、监听端是否应答、强制门户是否放行了设备,一概不作说明。

在添加依赖之前,先读已安装的单元以及任何 drop-in。给每个网络服务都加上宽泛的 After= 只会拖慢启动,并不能建立你真正需要的连接。

只为你能测试的那条依赖排序,其余一律用就绪探测来检查。能打开隧道的探测胜过靠猜的定时器。

隧道第一次起来之后会发生什么

开机只是众多事件之一。接入链路会变化,门户会话会过期,对端会重启。要把内部重连与服务管理器处理的进程退出区分开,因为两者的所有者不同,留下的证据也不同。

交互式认证会限制无人值守的恢复。后台单元不会解锁桌面钥匙串,也不会回应 MFA 提示,所以要遵循该服务场景下已批准的凭据安排。

另外单独决定隧道断开期间应用可以做什么。重试恢复的是连接,而拦截策略决定在这段空档里是否允许直连流量。

相关文章