屏幕一黑 VPN 就断:锁屏、息屏还是睡眠?
锁定的会话、熄灭的屏幕和进入睡眠的整台机器是三件不同的事。在责怪 VPN 保活机制之前,先用 journalctl 把它们对上号。
当有人说屏幕一黑 VPN 就死了,第一个有用的问题是三者中到底发生了哪一件:会话被锁定、显示器被关闭,还是整台机器进入睡眠。这是三套独立的机制、独立的计时器,其中只有一种能让进程完全排不上 CPU。请按顺序走完下面的检查。停在第一个能回答问题的检查上,因为后面的每一项都在回答别的问题。
检查一:把锁定、息屏和睡眠分开
锁定只改变谁有权使用这个会话;合成器照常绘制,网络栈照常运行,VPN 客户端毫无察觉。息屏在空闲一段时间后关掉面板,机器仍然完全清醒。睡眠会停掉 CPU,也就意味着任何用户态进程都排不上调度,保活间隔设得再短也发不出去。
| Event | What it stops | Can it kill the tunnel? |
|---|---|---|
| Session lock | Input to your session | No |
| Display blank | The panel | No |
| Suspend to RAM | CPU scheduling, hence every process | Yes, and silently |
| Hibernate | Everything, with state written to disk | Yes |
正是这张表说明「屏幕黑了」不是诊断。一台设为五分钟息屏、三十分钟睡眠的台式机,会在第六分钟显示黑屏,而隧道完全健康。第三十分钟的故障是另一件事、另一种修法,而隔着房间看,两者一模一样。
检查二:把电源和网络事件放到同一条时间线上
读一段有边界的时间窗,而不是整个启动过程,并把登录管理器和连接的所有者都包含进来:
journalctl -b -u systemd-logind -u NetworkManager --since "45 minutes ago"
systemd-inhibit --list
第一条命令显示睡眠请求、唤醒,以及随后发生的网络切换。第二条显示当前谁持有抑制锁,这能告诉你是否有东西在故意阻止睡眠,以及是哪个程序。如果你的连接所有者不是 NetworkManager,请相应调整单元名;同时记住,读取其他用户的单元或系统日志取决于本机策略。
缺少一行并不是否定结果。如果所选单元的日志对你的账户不可见,没有睡眠记录什么也证明不了;从一个空过滤器得出「它从未睡过」,正是人们花一周时间反复调保活参数的原因。
检查三:如果确实睡了,判断这是不是有意的
一旦时间线上出现睡眠转换,问题就从「VPN 为什么坏」变成「这台机器本来该不该睡」。在笔记本上答案常常是该睡,隧道中断是预期行为,客户端应在唤醒后恢复。在应当保持可访问的工作站上,该改的是睡眠策略。判断你面对的是这两种机器中的哪一种只需要一个问题,而这不是日志能替你回答的问题。
通过属于已登录会话的控件去改,或者在需求针对整机时使用管理员支持的机制。在另一个账户下登录时编辑显示管理器设置,并不是同一个动作,而且会一直看起来生效到下一次会话开始。彻底关掉电源管理是一种很宽的第一反应,它牺牲续航,也掩盖了真正的策略问题。
检查四:如果机器一直醒着,去看网络和客户端
一台醒着却丢了隧道的机器,只有三种故事:接入网络断了、VPN 客户端停止或重启了,或者服务端让关联过期而客户端仍以为连着。把底层链路事件的时间戳和隧道事件对比,并准确说清哪个在前。
然后把恢复路径和原会话分开测试。通过已恢复的隧道发出的新请求可以成功,而在中断前打开的长连接应用会话仍然是坏的,因为应用手里握着过期的套接字或缓存的地址。那是应用的问题,不是隧道没回来的证据。
一份有用的报告该包含什么
按时间顺序写清时间戳和负责人:会话何时锁定、屏幕何时变黑、有没有记录到睡眠请求、链路何时断开又恢复、隧道何时改变状态,以及应用实际做了什么。每一项都有负责人,因此每一项都能交给对的人,而不是变成一句泛泛的对 Linux 的抱怨。
如果这些行里有任何一行缺失,那才是接下来该测的东西,而不是接下来该改的东西。带缺口的时间线,比凭感觉改设置更有信息量。