前言

今天下午,我经历了一场堪称“完美风暴”的 WSL2 (Windows Subsystem for Linux) 故障。起初只是一个简单的 systemctl 命令报错,但随着排查的深入,问题如剥洋葱般层层展现,从上层应用一直牵扯到 Windows 的底层网络配置。最终,在经历了近乎“法医级别”的诊断后,我们成功让系统恢复了健康。

这不仅仅是一篇故障排除指南,更是一次对 WSL2 内部工作机制的深度探索。如果你也曾被 WSL2 的网络问题所困扰,那么这篇文章或许能为你提供一些思路和慰藉。

故障初现:systemctl 失效

一切始于一个常见的命令:

sudo systemctl enable --now ssh

得到的却是一个经典错误:

System has not been booted with systemd as init system (PID 1). Can't operate. Failed to connect to bus: Host is down

对于有经验的 WSL 用户来说,这通常意味着 systemd 没有启用。于是,我们按照官方推荐的方法,在 /etc/wsl.conf 中添加了配置:

[boot]
systemd=true

然后执行 wsl --shutdown 重启。然而,这只是噩梦的开始。

第一层迷雾:apt 网络中断

systemd 启用后,我们尝试运行 sudo apt update,却一头撞上了网络错误:

Temporary failure resolving 'archive.ubuntu.com'

这是一个典型的 DNS 解析失败错误。WSL 环境无法将域名转换为 IP 地址。常规的 wsl --shutdown 重启大法在此时也失去了魔力。

第二层迷雾:wsl.conf 配置失效与“安全模式”

我们尝试通过修改 /etc/wsl.conf 来手动指定 DNS,但配置似乎并未生效。更诡异的是,WSL 在启动时出现了一个不祥的提示:

wsl: 安全模式已启用 - 许多功能都将被禁用

“安全模式”意味着 /etc/wsl.conf 文件因语法错误等原因被 WSL 完全忽略。这解释了为什么我们所有的配置修改都石沉大海。在用 tee 命令确保配置文件格式绝对正确后,安全模式的提示消失了,但新的问题浮出水面。

第三层迷幕:NAT 模式失败与服务卡死

解决了安全模式后,WSL 启动时又抛出了新的警告:

wsl: 无法配置网络 (networkingMode Nat),回退到 networkingMode VirtioProxy。

这表明 WSL 首选的、最高效的 NAT 网络模式启动失败,被迫降级。更糟糕的是,在排查过程中,wsl --status 命令一度完全卡死,没有任何响应。这指向了问题的核心——WSL 的后台核心服务 LxssManager 已经处于死锁或无响应状态。

通过在 Windows 的 services.msc 中强行重启 LxssManager 服务,我们暂时解决了服务卡死的问题,但网络故障依旧。

拨云见日:systemd-resolved 的“致命一击”

在山重水复疑无路之际,一个决定性的发现在 cat /etc/resolv.conf 命令中出现了:

# This is /run/systemd/resolve/stub-resolv.conf managed by...
nameserver 127.0.0.53

真相大白!

  1. 我们的 systemd=true 配置早已成功生效
  2. systemd 启动后,其内置的 systemd-resolved 服务接管了系统的 DNS 解析,将 DNS 服务器指向了它自己 (127.0.0.53)。
  3. 然而,systemd-resolved 服务本身也处于一个无法访问外部网络的环境中(因为底层的 NAT 模式失败了)。
  4. 这就形成了一个致命的死循环:aptsystemd-resolved 请求 DNS,而 systemd-resolved 自己也上不了网,无法给出答案。

我们之前所有修改 /etc/resolv.conf 的尝试都失败了,因为 systemd-resolved 在每次启动时都会强制重建这个文件(或其符号链接),覆盖我们的修改。

最终解决方案:釜底抽薪

找到了问题的根源,解决方案便清晰明了:我们必须绕过这个“空转”的 systemd-resolved

  1. 解锁文件sudo chattr -i /etc/resolv.conf
  2. 删除符号链接sudo rm /etc/resolv.conf
  3. 创建静态配置sudo sh -c 'echo "nameserver 8.8.8.8" > /etc/resolv.conf'
  4. 锁定文件sudo chattr +i /etc/resolv.conf,防止 systemd-resolved 再次篡改。

执行完毕,再次运行 sudo apt update,久违的 Hit: ... 终于出现。网络,通了!

故障回顾与反思

这场“故障风暴”的根源在于 Windows 底层 Hyper-V 网络组件的异常,它引发了 WSL 网络模式降级,并与成功启用的 systemd-resolved 服务形成了一个难以排查的故障放大回路。

这次经历带给我们几个重要的教训:

虽然过程曲折,但这次“寻宝游戏”般地排错,无疑让我们对 WSL2 这个强大工具的理解更进了一步。希望这篇记录,也能成为你工具箱中的一张备用地图。