排查适用于 Linux 的 Windows 子系统问题

我们在下面介绍了一些与 WSL 相关的常见故障排除场景,但也请考虑在 GitHub 上的 WSL 产品存储库中搜索已提交的问题。

提交问题、bug 报告、功能请求

借助 WSL 产品存储库问题,可进行以下操作:

  • 搜索现有问题,查看是否存在任何与遇到的问题相关的问题。 请注意,在搜索栏中可以删除“is:open”,以便在搜索中包括已解决的问题。 请考虑对任何希望优先处理的未解决问题发表评论或点赞。
  • 提交新问题。 如果发现 WSL 存在问题,并且该问题不像是已有的问题,你可以选择绿色的“新问题”按钮,然后选择“WSL - Bug 报告” 。 需要在其中提供以下信息:问题的标题、Windows 内部版本号(运行 cmd.exe /c ver 查看当前的内部版本号)、运行的是 WSL 1 还是 2、当前的 Linux 内核版本号(运行 wsl.exe --statuscat /proc/version)、发行版的版本号(运行 lsb_release -r)、涉及的任何其他软件版本、重现步骤、预期行为、实际行为和诊断日志(如果可用且适当)。 有关详细信息,请参阅参与 WSL 工作
  • 提交功能请求,方法是选择绿色的“新问题”按钮,然后选择“功能请求” 。 需要回答几个描述你的请求的问题。

也可执行以下操作:

安装问题

  • 安装失败并出现错误 0x80070003

    • 适用于 Linux 的 Windows 子系统只能在系统驱动器(通常是 C: 驱动器)中运行。 请确保分发版存储在系统驱动器上:
    • 在 Windows 10 上打开“设置”->“系统”->“存储”->“更多存储设置: 更改新内容的保存位置”用于在 C: 驱动器中安装应用的系统设置屏幕截图 (Windows 10)
    • 在 Windows 11 上打开“设置”->“系统”->“存储”->“高级存储设置”->“新内容的保存位置”用于在 C: 驱动器中安装应用的系统设置屏幕截图 (Windows 11)
  • WslRegisterDistribution 失败并出现错误 0x8007019e

    • 未启用“适用于 Linux 的 Windows 子系统”可选组件:
    • 打开“控制面板”->“程序和功能”->“打开或关闭 Windows 功能”-> 选中“适用于 Linux 的 Windows 子系统”,或使用本文开头所述的 PowerShell cmdlet。
  • 安装失败,出现错误 0x80070003 或错误 0x80370102

    • 请确保在计算机的 BIOS 内已启用虚拟化。 有关如何执行此操作的说明因计算机而异,并且很可能在 CPU 相关选项下。
    • WSL2 要求 CPU 支持二级地址转换 (SLAT) 功能,后者已在 Intel Nehalem 处理器(Intel Core 第一代)和 AMD Opteron 中引入。 即使成功安装了虚拟机平台,旧版 CPU(例如 Intel Core 2 Duo)也无法运行 WSL2。
  • 尝试升级时出错:Invalid command line option: wsl --set-version Ubuntu 2

    • 请确保已启用适用于 Linux 的 Windows 子系统,并且你使用的是 Windows 内部版本 18362 或更高版本。 若要启用 WSL,请在 PowerShell 提示符下以具有管理员权限的身份运行此命令:Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
  • 由于虚拟磁盘系统的某个限制,无法完成所请求的操作。 虚拟硬盘文件必须是解压缩的且未加密的,并且不能是稀疏的。

    • 打开 Linux 发行版的配置文件文件夹,取消选中“压缩内容”(如果已选中“加密内容”,请一并取消选中)。 它应位于 Windows 文件系统上的一个文件夹中,类似于:%USERPROFILE%\AppData\Local\Packages\CanonicalGroupLimited...
    • 在此 Linux 发行版配置文件中,应存在一个 LocalState 文件夹。 右键单击此文件夹可显示选项的菜单。 选择“属性”>“高级”,然后确保未选中(未勾选)“压缩内容以节省磁盘空间”和“加密内容以保护数据”复选框。 如果系统询问是要将此应用到当前文件夹还是应用到所有子文件夹和文件,请选择“仅此文件夹”,因为你只是要清除压缩标志。 完成此操作后,wsl --set-version 命令应正常工作。

WSL 发行版属性设置的屏幕截图

备注

在我的示例中,我的 Ubuntu 18.04 发行版的 LocalState 文件夹位于 C:\Users<my-user-name>\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu18.04onWindows_79rhkp1fndgsc

请检查 WSL Docs GitHub 主题 #4103,其中跟踪了此问题以提供更新的信息。

  • 无法将词语“wsl”识别为 cmdlet、函数、脚本文件或可运行程序的名称。

  • 错误:适用于 Linux 的 Windows 子系统未安装发行版。

    • 如果你在已安装 WSL 发行版之后收到此错误:
    1. 请先运行该发行版一次,然后在从命令行中调用它。
    2. 检查你是否正在运行单独的用户帐户。 运行具有提升权限(在管理员模式下)的主要用户帐户应该不会导致出现此错误,但你应确保你未在无意中运行 Windows 附带的内置管理员帐户。 这是单独的用户帐户,根据设计将不显示任何已安装的 WSL 发行版。 有关详细信息,请参阅启用和禁用内置 Administrator 帐户
    3. WSL 可执行文件仅安装到本机系统目录中。 在 64 位 Windows 上运行 32 位进程(若在 ARM64 上,则为任何非本机组合)时,托管的非本机进程实际上会看到一个不同的 System32 文件夹。 (32 位进程在 x64 Windows 上看到的文件夹存储在磁盘上的 \Windows\SysWOW64。)可通过在虚拟文件夹 \Windows\sysnative 中查找,从托管进程访问“本机”system32。 请记住,它实际上不会存在于磁盘上,不过文件系统路径解析程序会找到它。
  • 错误:此更新仅适用于装有适用于 Linux 的 Windows 子系统的计算机。

    • 若要安装 Linux 内核更新 MSI 包,需要 WSL,应先启用它。 如果失败,将看到以下消息:This update only applies to machines with the Windows Subsystem for Linux
    • 出现此消息有三个可能的原因:
    1. 你仍使用旧版 Windows,不支持 WSL 2。 有关版本要求和要更新的链接,请参阅步骤 #2。

    2. 未启用 WSL。 需要返回到步骤 #1,并确保在计算机上启用了可选的 WSL 功能。

    3. 启用 WSL 后,需要重新启动才能使其生效,请重新启动计算机,然后重试。

  • 错误: WSL 2 要求对其内核组件进行更新。 若需了解相关信息,请访问 https://aka.ms/wsl2kernel

    • 如果 %SystemRoot%\system32\lxss\tools 文件夹中缺少 Linux 内核包,会遇到此错误。 若要解决此问题,请在安装说明的步骤 #4 中安装 Linux 内核更新 MSI 包。 可能会需要从“添加或删除程序”卸载 MSI,然后重新安装。

常见问题

我在使用 Windows 10 版本 1903,但我还是没看见 WSL 2 选项

这可能是因为你的计算机尚未实现对 WSL 2 的向后移植。 要解决此问题,最简单的方法是转到 Windows 设置,然后打击“检查更新”,在你的系统上安装最新更新。 查看有关实现向后移植的完整说明

如果你点击了“检查更新”,但仍未收到更新,可以手动安装 KB KB4566116

错误:使用 wsl --set-default-version 2 时显示 0x1bc

当“显示语言”或“系统区域设置”未设为英语时,可能会发生此情况。

wsl --set-default-version 2
Error: 0x1bc
For information on key differences with WSL 2 please visit https://aka.ms/wsl2

0x1bc 的实际错误为:

WSL 2 requires an update to its kernel component. For information please visit https://aka.ms/wsl2kernel

有关详细信息,请查看问题 5749

无法从 Windows 访问 WSL 文件

9p 协议文件服务器在 Linux 端提供服务,以允许 Windows 访问 Linux 文件系统。 如果在 Windows 上无法使用 \\wsl$ 访问 WSL,则可能是因为 9P 无法正确启动。

要检查这一点,可以使用 dmesg |grep 9p 来检查启动日志,这将显示任何错误。 成功的输出如下所示:

[    0.363323] 9p: Installing v9fs 9p2000 file system support
[    0.363336] FS-Cache: Netfs '9p' registered for caching
[    0.398989] 9pnet: Installing 9P2000 support

请参阅此 GitHub 主题获取有关此问题的进一步讨论。

无法启动 WSL 2 发行版,仅在输出中看到“WSL 2”

如果你的显示语言不是英语,则可能会看到截断的错误文本。

C:\Users\me>wsl
WSL 2

要解决此问题,请访问 https://aka.ms/wsl2kernel,按照该文档页面上的指示手动安装内核。

在 Linux 中执行 Windows .exe 时,显示 command not found

用户可以直接从 Linux 运行 notepad.exe 等 Windows 可执行文件。 有时,你可能会点击“找不到命令”,如下所示:

$ notepad.exe
-bash: notepad.exe: command not found

如果 $PATH 中没有 Win32 路径,互操作将找不到 .exe。 可以通过在 Linux 中运行 echo $PATH 来进行验证。 应该会在输出中看到 Win32 路径(例如 /mnt/c/Windows)。 如果看不到任何 Windows 路径,则很可能是 Linux shell 覆盖了 PATH。

以下是 Debian 上的 /etc/profile 导致此问题的一个示例:

if [ "`id -u`" -eq 0 ]; then
  PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
else
  PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games"
fi

Debian 上的正确方法是删除以上行。 还可在赋值过程中追加 $PATH(如下所示),但这可能导致 WSL 和 VSCode 的一些其他问题

if [ "`id -u`" -eq 0 ]; then
  PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH"
else
  PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:$PATH"
fi

有关详细信息,请参阅问题 5296 和问题 5779

Windows 更新后出现“错误:0x80370102 由于未安装所需功能,因此无法启动虚拟机。”

请启用 Virtual Machine Platform Windows 功能,并确保在 BIOS 中启用了虚拟化。

  1. 请查看 Hyper-V 系统要求

  2. 如果你的计算机是 VM,请手动启用嵌套虚拟化。 以管理员身份启动 Powershell,然后运行以下命令,将 <VMName> 替换为主机系统上虚拟机的名称(可在 Hyper-V 管理器中找到):

    Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $true
    
  3. 请按照电脑制造商提供的虚拟化启用指南进行操作。 通常,这可能涉及使用系统 BIOS 来确保在 CPU 上启用了这些功能。 此过程的说明可能因计算机而异,有关示例,请参阅来自 Bleeping Computer 的本文

  4. 启用 Virtual Machine Platform 可选组件后,请重启计算机。

  5. 确保在启动配置中启用了虚拟机监控程序启动。 可以通过运行(提升的 PowerShell)来对此进行验证:

     bcdedit /enum | findstr -i hypervisorlaunchtype
    

    如果看到 hypervisorlaunchtype Off,则会禁用虚拟机监控程序。 使其在提升的 PowerShell 中运行:

     bcdedit /set hypervisorlaunchtype Auto
    
  6. 此外,如果安装了第三方虚拟机监控程序(例如 VMware 或 VirtualBox),请确保安装其最新版本(VMware 15.5.5+VirtualBox 6+这些版本可以支持 HyperV)或关闭它们。

  7. 如果在 Azure 虚拟机上收到此错误,检查以确保受信任的启动已禁用。 Azure 虚拟机不支持嵌套虚拟化

详细了解在虚拟机中运行 Hyper-V 时如何配置嵌套虚拟化

WSL 在工作计算机上或在企业环境中没有网络连接

业务或企业环境可能已将 Windows Defender防火墙设置配置为阻止未经授权的网络流量。 如果本地规则合并设置为“否”,则 WSL 网络在默认情况下无效,并且管理员需要添加防火墙规则以允许它。

可以按照以下步骤确认本地规则合并的设置:

Windows 防火墙设置屏幕截图

  1. 打开“高级安全 Windows Defender 防火墙”(这不是“控制面板”中的“Windows Defender 防火墙”)
  2. 右键单击“本地计算机上的高级安全 Windows Defender 防火墙”选项卡
  3. 选择“属性”
  4. 在打开的新窗口中选择“公共配置文件”选项卡
  5. 在“设置”部分下选择“自定义”
  6. 在打开的“自定义公共配置文件的设置”窗口中查看“规则合并”是否设置为“否”。 这将阻止对 WSL 的访问。

可在配置 Hyper-V 防火墙中找到有关如何更改此防火墙设置的说明。

WSL 在连接到 VPN 后没有网络连接

如果在连接到 Windows 上的 VPN 后 bash 断开网络连接,请尝试从 bash 内部解决问题。 此解决方法允许通过 /etc/resolv.conf 手动替代 DNS 解析。

  1. 执行 ipconfig.exe /all,记下 VPN 的 DNS 服务器
  2. 执行 sudo cp /etc/resolv.conf /etc/resolv.conf.new,创建现有 resolv.conf 的副本
  3. 执行 sudo unlink /etc/resolv.conf 以便与当前 resolv.conf 取消链接
  4. sudo mv /etc/resolv.conf.new /etc/resolv.conf
  5. 编辑 /etc/wsl.conf 并将此内容添加到文件。 (有关此设置的详细信息,请参阅高级设置配置
[network]
generateResolvConf=false
  1. 打开 /etc/resolv.conf 并执行以下操作
    a. 从文件中删除第一行,其中包含描述自动生成的注释
    b. 将上面步骤 (1) 中记下的 DNS 条目添加为 DNS 服务器列表中的第一个条目。
    c. 关闭该文件。

断开 VPN 连接后,必须将更改还原为 /etc/resolv.conf。 为此,请执行以下命令:

  1. cd /etc
  2. sudo mv resolv.conf resolv.conf.new
  3. sudo ln -s ../run/resolvconf/resolv.conf resolv.conf

NAT 模式下 WSL 的 Cisco Anyconnect VPN 问题

Cisco AnyConnect VPN 修改路由的方式阻止了 NAT 正常工作。 有一种特定于 WSL 2 的解决方法:请参阅 Cisco AnyConnect 安全移动客户端管理员指南,版本 4.10 - 排查 AnyConnect 问题

镜像网络模式处于打开状态时 VPN 的 WSL 连接问题

镜像网络模式目前是 WSL 配置中的实验性设置。 WSL 传统的 NAT 网络体系结构可以更新为一种全新的网络模式,称为“镜像网络模式”。 当实验性的 networkingMode 设置为 mirrored 时,Windows 上的网络接口将镜像到 Linux 中以提高兼容性。 有关详细信息,请参阅命令行博客:WSL 2023 年 9 月更新

已测试并确认某些 VPN 与 WSL 不兼容,包括:

  • “Bitdefender”版本 26.0.2.1
  • “OpenVPN”版本 2.6.501
  • “Mcafee Safe Connect”版本 2.16.1.124

在 WSL 中对 HttpProxy 镜像使用 autoProxy 时的注意事项

可以使用 WSL 配置文件的实验部分中的 autoProxy 设置来配置 HTTP/S 代理镜像。 应用此设置时,请注意以下注意事项:

  • PAC 代理:WSL 将通过设置“WSL_PAC_URL”环境变量在 Linux 中配置设置。 默认情况下,Linux 不支持 PAC 代理。
  • 与 WSLENV 的交互:用户定义的环境变量优先于此功能指定的环境变量

启用后,以下内容适用于 Linux 分发版上的代理设置:

  • Linux 环境变量 HTTP_PROXY 设置为在 Windows HTTP 代理配置中安装的一个或多个 HTTP 代理。
  • Linux 环境变量 HTTPS_PROXY 设置为在 Windows HTTPS 代理配置中安装的一个或多个 HTTP 代理
  • Linux 环境变量 NO_PROXY 设置为绕过在 Windows 配置目标中找到的任何 HTTP/S 代理。
  • WSL_PAC_URL 之外的每个环境变量都设置为小写和大写。 例如 HTTP_PROXYhttp_proxy

ZScaler 配置引起了一个已知的问题,即 ZScaler 重复启用和禁用 Windows 代理配置,导致 WSL 反复显示“在主机上检测到 Http 代理更改”通知。

有关详细信息,请参阅命令行博客:WSL 2023 年 9 月更新

DNS 隧道的网络注意事项

当 WSL 无法连接到 Internet 时,可能是因为对 Windows 主机的 DNS 调用被阻止。 这是因为现有网络配置阻止了 WSL VM 发送到 Windows 主机的 DNS 网络数据包。 DNS 隧道修复了此问题,方法是使用虚拟化功能直接与 Windows 通信,从而无需发送网络数据包即可解析 DNS 名称。 此功能应提高网络兼容性,并可支持实现更好的 Internet 连接,即使你拥有 VPN、特定防火墙设置或其他网络配置。

可以使用 WSL 配置文件的实验部分中的 dnsTunneling 设置来配置 DNS 隧道。 应用此设置时,请注意以下注意事项:

  • 如果将 VPN 与 WSL 配合使用,请启用 DNS 隧道。 许多 VPN 使用 NRPT 策略,这些策略仅在启用 DNS 隧道时应用于 WSL DNS 查询。
  • Linux 分发版中的 /etc/resolv.conf 文件有 3 个 DNS 服务器的最大限制,而 Windows 可能使用超过 3 个 DNS 服务器。 使用 DNS 隧道可消除此限制 - Linux 现在可以使用所有 Windows DNS 服务器。
  • WSL 按以下顺序使用 Windows DNS 后缀(类似于 Windows DNS 客户端使用的顺序):
    1. 全局 DNS 后缀
    2. 补充 DNS 后缀
    3. 每个接口的 DNS 后缀
    4. 如果在 Windows 上启用了 DNS 加密(DoH、DoT),加密将应用于来自 WSL 的 DNS 查询。 如果用户想要在 Linux 中启用 DoH、DoT,则需要禁用 DNS 隧道。
  • 来自 Docker Desktop 管理的 Docker 容器的 DNS 查询将绕过 DNS 隧道。 Docker Desktop 采用自己的方式(不同于 DNS 隧道)将主机 DNS 设置和策略应用于来自 Docker 容器的 DNS 查询。
  • 若要成功启用 DNS 隧道,则不应禁用 wsl.conf 文件中的 generateResolvConf 选项。
  • 启用 DNS 隧道后,将忽略 wsl.conf 文件中的 generateHosts 选项(Windows DNS 主机文件不会复制到 Linux /etc/hosts 文件中)。 Windows 主机文件中的策略将应用于 Linux 中的 DNS 查询,而无需将相应文件复制到 Linux 中。

有关详细信息,请参阅命令行博客:WSL 2023 年 9 月更新

将 Windows 主机收到的入站流量引导至 WSL 虚拟机时出现问题

使用镜像网络模式(实验性 networkingMode 设置为 mirrored)时,Windows 主机收到的一些入站流量永远不会被引导到 Linux VM。 此流量如下所示:

  • UDP 端口 68 (DHCP)
  • TCP 端口 135(DCE 终结点解析)
  • TCP 端口 1900 (UPnP)
  • TCP 端口 2869 (SSDP)
  • TCP 端口 5004 (RTP)
  • TCP 端口 3702 (WSD)
  • TCP 端口 5357 (WSD)
  • TCP 端口 5358 (WSD)

使用镜像网络模式时,WSL 将自动配置某些 Linux 网络设置。 不支持在使用镜像网络模式时对这些设置进行任何用户配置。 下面是 WSL 将配置的设置列表:

在默认网络命名空间下运行时,启用了镜像网络模式的 WSL2 中出现 Docker 容器问题

存在一个已知问题,即无法创建具有已发布端口 (docker run –publish/-p) 的 Docker Desktop 容器。 WSL 团队正在与 Docker Desktop 团队合作解决此问题。 要解决此问题,请在 Docker 容器中使用主机的网络命名空间。 通过“docker run”命令中使用的“--network host”选项设置网络类型。 另一种解决方法是在 WSL 配置文件中的实验部分ignoredPorts 设置中列出已发布的端口号。

Docker 容器在其网络管理器运行时出现问题

运行网络管理器服务的 Docker 容器存在一个已知问题。 症状包括在尝试与主机建立环回连接时失败。 建议停止网络管理器服务,以便正确配置 WSL 网络。

sudo systemctl disable network-manager.service

解析 WSL 中的 .local 名称

若要在不需要传统 DNS 服务器的情况下将主机名解析为本地网络中的 IP 地址,通常使用 .local 名称。 这是通过 mDNS(多播 DNS)协议实现的,该协议依赖于多播流量来运行。

networkingMode 设置为 NAT:

目前,启用了 DNS 隧道时不支持此功能。 若要启用 .local 名称的解析,建议使用以下解决方案:

  • 禁用 DNS 隧道。
  • 使用镜像网络模式。

networkingMode 设置为 Mirrored:

注意:你需要使用 WSL 内部版本 2.3.17 或更高版本,才能提供以下功能。

由于镜像模式支持多播流量,因此可以使用 mDNS(多播 DNS)协议来解析 .local 名称。 必须将 Linux 配置为支持 mDNS,因为它默认情况下不支持。 配置它的一种方法是使用以下两个步骤:

  1. 安装“libnss-mdns”程序包
sudo apt-get install libnss-mdns

*“libnss-mdns”程序包是 GNU C 库 (glibc) 的 GNU 名称服务交换机 (NSS) 功能的插件,它通过多播 DNS (mDNS) 提供主机名解析。 此程序包实际上允许常见的 Unix/Linux 程序解析临时 mDNS 域 .local 中的名称。

  1. 配置 /etc/nsswitch.conf 文件以在“hosts”部分中启用“mdns_minimal”设置。 文件的示例内容:
cat /etc/nsswitch.conf
# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc-reference' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.

passwd:         compat systemd
group:          compat systemd
shadow:         compat
gshadow:        files

hosts:          files mdns_minimal [NOTFOUND=return] dns
networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis

WSL 中的 DNS 后缀

根据 .wslconfig 文件中的配置,WSL 将具有以下行为 wrt DNS 后缀:

当 networkingMode 设置为 NAT 时:

案例 1)默认情况下,Linux 中不配置 DNS 后缀

案例 2)如果启用 DNS 隧道(.wslconfig 中的 dnsTunneling 设置为 true),则在 /etc/resolv.conf 的“搜索”设置中,在 Linux 中配置所有 Windows DNS 后缀

后缀在 /etc/resolv.conf 中按照以下顺序进行配置,类似于 Windows DNS 尝试后缀的顺序,即先解析 name: global DNS 后缀,然后解析补充 DNS 后缀,再解析每个接口的 DNS 后缀。

当 Windows DNS 后缀发生更改时,该更改将自动反映在 Linux 中

案例 3)如果禁用了 DNS 隧道以及 SharedAccess DNS 代理(.wslconfig 中的 dnsTunneling 和 dnsProxy 都设置为 false),则在 /etc/resolv.conf 的“域”中,在 Linux 中配置单个 DNS 后缀

当 Windows DNS 后缀发生更改时,该更改不会反映在 Linux 中

Linux 中配置的单个 DNS 后缀是从每个接口 DNS 后缀中选择的(忽略全局和补充后缀)

如果 Windows 有多个接口,则会使用启发式选择将在 Linux 中配置的单个 DNS 后缀。 例如,如果 Windows 上有 VPN 接口,则从该接口中选择后缀。 如果没有 VPN 接口,则从最有可能提供 Internet 连接的接口中选择后缀。

当 networkingMode 设置为“已镜像”时:

所有 Windows DNS 后缀都在 Linux 中的 /etc/resolv.conf 的“搜索”设置中进行配置

后缀在 /etc/resolv.conf 中的配置顺序与在 NAT 模式案例 2)中的顺序相同

当 Windows DNS 后缀发生更改时,该更改将自动反映在 Linux 中

注意:在 Windows 中,可以使用 SetInterfaceDnsSettings - Win32 apps | Microsoft Learn 配置补充 DNS 后缀,带有标记“DNS_SETTING_SUPPLEMENTAL_SEARCH_LIST 在“设置”参数中设置

在 WSL 中排查 DNS 问题

当 WSL 在 NAT 模式下启动容器时的默认 DNS 配置是让 Windows 主机上的 NAT 设备充当 WSL 容器的 DNS“服务器”。 当 DNS 查询从 WSL 容器发送到 Windows 主机上的 NAT 设备时,DNS 数据包将从 NAT 设备转发到主机上的共享访问服务;响应以反向发送回 WSL 容器。 此数据包转发过程到共享访问需要防火墙规则才能允许入站 DNS 数据包,当 WSL 最初要求 HNS 为其 WSL 容器创建 NAT 虚拟网络时,该数据包由 HNS 服务创建。

由于采用这种 NAT - 共享访问设计,有几个已知配置可能会中断 WSL 的名称解析。

1.企业可以推送不允许本地定义的防火墙规则的策略,只允许企业策略定义的规则。

如果这是企业设置的,则会忽略 HNS 创建的防火墙规则,因为它是本地定义的规则。 若要使此配置正常工作,企业必须创建防火墙规则,以允许 UDP 端口 53 到共享访问服务,或者 WSL 可以设置为使用 DNS 隧道。 可以通过运行以下内容来查看是否配置为不允许本地定义的防火墙规则。 请注意,这将显示所有 3 个配置文件的设置:域、专用和公用。 如果已在任何配置文件上设置,则如果为 WSL vNIC 分配该配置文件(默认值为“公用”),则会阻止该数据包。 这只是 Powershell 中返回的第一个防火墙配置文件的代码片段:

PS C:\> Get-NetFirewallProfile -PolicyStore ActiveStore
Name                            : Domain
Enabled                         : True
DefaultInboundAction            : Block
DefaultOutboundAction           : Allow
AllowInboundRules               : True
AllowLocalFirewallRules         : False

AllowLocalFirewallRules:False means the locally defined firewall rules, like that by HNS, will not be applied or used.

2.企业可以向下推送阻止所有入站规则的组策略和 MDM 策略设置。

此类设置将覆盖任何允许入站防火墙规则。 因此,此设置将阻止 HNS 创建的 UDP 防火墙规则,从而阻止 WSL 解析名称。 若要运行此配置,必须将 WSL 设置为使用 DNS 隧道。此设置将始终阻止 NAT DNS 代理。

从组策略:

Computer Configuration \ Administrative Templates \ Network \ Network Connections \ Windows Defender Firewall \ Domain Profile | Standard Profile

“Windows Defender 防火墙:不允许例外” - 已启用

从 MDM 策略:

./Vendor/MSFT/Firewall/MdmStore/PrivateProfile/Shielded

./Vendor/MSFT/Firewall/MdmStore/DomainProfile/Shielded

./Vendor/MSFT/Firewall/MdmStore/PublicProfile/Shielded

可通过运行以下命令,查看是否配置为不允许任何入站防火墙规则(请参阅上述关于防火墙配置文件的注意事项)。 这只是 Powershell 中返回的第一个防火墙配置文件的代码片段:


PS C:\> Get-NetFirewallProfile -PolicyStore ActiveStore
Name                            : Domain
Enabled                         : True
DefaultInboundAction            : Block
DefaultOutboundAction           : Allow
AllowInboundRules               : False

AllowInboundRules: False means that no inbound Firewall rules will be applied.

3.用户通过Windows 安全设置应用并检查“阻止所有传入连接(包括允许的应用列表中的连接)”的控件

Windows 支持用户选择加入上述案例 2 中引用的企业可应用的相同设置。 用户可以打开“Windows 安全”设置页,选择“防火墙和网络保护”选项,选择要配置的防火墙配置文件(域、专用或公共),并在“传入连接”下检查标记为“阻止所有传入连接,包括允许的应用列表中的连接”的控件。

如果为公共配置文件设置了此设置(这是 WSL vNIC 的默认配置文件),则 HNS 创建的防火墙规则将阻止 UDP 数据包进行共享访问。

必须取消选中 NAT DNS 代理配置才能从 WSL 工作,或者可以将 WSL 设置为使用 DNS 隧道。

4.允许 DNS 数据包共享访问的 HNS 防火墙规则可能无效,引用以前的 WSL 接口标识符。 这是 HNS 中的一处缺陷,在最新的 Windows 11 版本已得到修复。 在早期版本中如果发生这种情况,虽然不容易发现,但有一个简单的解决方法:

  • 停止 WSL

    wsl.exe –shutdown

  • 删除旧的 HNS 防火墙规则。 大多数情况下,此 Powershell 命令应正常工作:

    Get-NetFirewallRule -Name "HNS*" | Get-NetFirewallPortFilter | where Protocol -eq UDP | where LocalPort -eq 53 | Remove-NetFirewallRule

  • 移除所有 HNS 终结点。 注意:如果使用 HNS 管理其他容器(例如 MDAG 或 Windows 沙盒),则还应停止这些容器。

    hnsdiag.exe delete all

  • 重新启动或重启 HNS 服务

    Restart-Service hns

  • 重启 WSL 后,HNS 将创建新的防火墙规则,并正确面向 WSL 接口。

排查 Windows 上的网络访问问题

如果没有网络访问权限,可能是因为配置错误。 请查看 FSE 驱动程序是否正在运行:“sc queryex FSE”。 如果未显示 FSE 正在运行,请检查 PortTrackerEnabledMode 注册表值是否在此注册表项下存在:reg query HKLM\System\CurrentControlSet\Services\Tcpip\Parameters。 如果 FSE 未运行或安装,并且 PortTrackerEnabledMode 存在,请删除该注册表值并重启动

手动删除虚拟适配器的方法

幽灵适配器,或称虚拟即插即用 (PnP) 设备,指在系统中显示但未物理连接的硬件组件。 这些“幽灵”设备可能会导致系统设置中的混乱和杂乱。 如果在虚拟机 (VM) 中运行 WSL 时看到幽灵适配器,请按照以下手动步骤查找和删除这些虚拟即插即用设备。 Microsoft 正在开发不需要手动干预的自动化解决方案。 更多信息即将推出。

  1. 打开“设备管理器”
  2. 查看 >“显示隐藏的设备”

设备管理器“显示隐藏的设备”菜单的屏幕截图

  1. 打开网络适配器

网络适配器列表的屏幕截图

  1. 右键单击幽灵网络适配器并选择“卸载设备”

右键单击网络列表中的虚拟 pnp 并选择卸载设备的屏幕截图

启动 WSL 或安装分发版会返回一个错误代码

按照 GitHub 上 WSL 存储库中收集 WSL 日志的说明收集详细日志,并在我们的 GitHub 上提交问题。

更新 WSL

适用于 Linux 的 Windows 子系统有两个组件需要更新。

  1. 若要更新适用于 Linux 的 Windows 子系统本身,请在 PowerShell 或 CMD 中使用命令 wsl --update

  2. 若要更新特定的 Linux 发行版用户二进制文件,请在要更新的 Linux 发行版中使用命令:apt-get update | apt-get upgrade

Apt-get upgrade 错误

某些包使用我们尚未实现的功能。 例如,udev 尚不受支持,会导致多个 apt-get upgrade 错误。

若要解决与 udev 相关的问题,请执行以下步骤:

  1. 将以下内容写入 /usr/sbin/policy-rc.d 并保存更改。

    #!/bin/sh
    exit 101
    
  2. 将执行权限添加到 /usr/sbin/policy-rc.d

    chmod +x /usr/sbin/policy-rc.d
    
  3. 运行以下命令:

    dpkg-divert --local --rename --add /sbin/initctl
    ln -s /bin/true /sbin/initctl
    

Windows 更新后出现“错误:0x80040306”

此错误与我们不支持旧版控制台这一事实有关。 若要关闭旧版控制台:

  1. 打开 cmd.exe
  2. 右键单击标题栏 -> 选择“属性”-> 取消选中“使用旧版控制台”
  3. 单击“确定”

Windows 更新后出现“错误:0x80040154”

在 Windows 更新期间可能禁用了“适用于 Linux 的 Windows 子系统”功能。 如果出现这种情况,则必须重新启用 Windows 功能。 在手动安装指南中可以找到有关启用“适用于 Linux 的 Windows 子系统”的说明。

更改显示语言

WSL 安装会尝试自动更改 Ubuntu 区域设置,使之与 Windows 安装的区域设置相匹配。 如果你不希望出现此行为,可以在安装完成后,运行此命令来更改 Ubuntu 区域设置。 必须重新启动 bash.exe 才能使此项更改生效。

以下示例将区域设置更改为 en-US

sudo update-locale LANG=en_US.UTF8

Windows 系统还原后出现的安装问题

  1. 删除 %windir%\System32\Tasks\Microsoft\Windows\Windows Subsystem for Linux 文件夹。
    注意:如果可选功能已完全安装且工作正常,请不要执行此操作。
  2. 启用 WSL 可选功能(如果尚未这样做)
  3. 重新启动
  4. lxrun /uninstall /full
  5. 安装 bash

在 WSL 中无法进行 Internet 访问

某些用户已报告特定的防火墙应用程序会阻止 WSL 中的 Internet 访问的问题。 报告的防火墙包括:

  1. Kaspersky
  2. AVG
  3. Avast
  4. Symantec Endpoint Protection

在某些情况下,关闭防火墙即可进行访问。 在某些情况下,只需让安装的防火墙在表面上阻止访问。

如果使用的是 Microsoft Defender 防火墙,取消选中“阻止所有传入连接,包括位于允许应用列表中的应用。”将允许访问。

使用 ping 时出现“权限被拒绝”错误

对于 Windows 周年更新版本 1607,在 WSL 中运行 ping 命令需要拥有 Windows 中的管理员特权。 若要运行 ping,请以管理员身份运行 Windows 上的 Ubuntu Bash,或使用管理员特权从 CMD/PowerShell 提示符运行 bash.exe。

对于更高版本的 Windows(内部版本 14926 及更高版本),则不再需要管理员特权。

Bash 挂起

如果使用 bash 时发现 bash 挂起(或死锁)且不响应输入,请收集并报告内存转储来帮助我们诊断问题。 请注意,这些步骤会导致系统崩溃。 如果你不熟悉此过程,请不要这样做,或者,请在执行此操作之前保存你的工作。

收集内存转储

  1. 将内存转储类型更改为“完整内存转储”。 更改转储类型时,请记下当前类型。

  2. 遵循这些步骤使用键盘控制来配置崩溃。

  3. 再现挂起或死锁场景。

  4. 使用步骤 (2) 中的按键顺序来使系统崩溃。

  5. 系统将会崩溃并收集内存转储。

  6. 系统重新启动后,会将 memory.dmp 报告给 secure@microsoft.com。 转储文件的默认位置是 %SystemRoot%\memory.dmp 或 C:\Windows\memory.dmp(如果 C: 是系统驱动器)。 请注意,在电子邮件中,转储供 WSL 或 Windows 上的 Bash 团队参考。

  7. 将内存转储类型还原为原始设置。

检查内部版本号

若要查找电脑的体系结构和 Windows 内部版本号,请打开
“设置”>“系统”>“关于”

查看“OS 内部版本”和“系统类型”字段。
“内部版本”和“系统类型”字段的屏幕截图

若要查找 Windows Server 内部版本号,请在 PowerShell 中运行以下命令:

systeminfo | Select-String "^OS Name","^OS Version"

确认已启用 WSL

可通过在提升的 PowerShell 窗口中运行以下命令来确认是否已启用“适用于 Linux 的 Windows 子系统”:

Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

OpenSSH 服务器连接问题

尝试连接 SSH 服务器失败并出现以下错误:“127.0.0.1 端口 22 已关闭连接”。

  1. 确保 OpenSSH 服务器正在运行:

    sudo service ssh status
    

    并已按照此教程进行操作: https://ubuntu.com/server/docs/service-openssh

  2. 停止 sshd 服务,然后在调试模式下启动 sshd:

    sudo service ssh stop
    sudo /usr/sbin/sshd -d
    
  3. 检查启动日志,确保已提供主机密钥,并且未看到如下所示的日志消息:

    debug1: sshd version OpenSSH_7.2, OpenSSL 1.0.2g  1 Mar 2016
    debug1: key_load_private: incorrect passphrase supplied to decrypt private key
    debug1: key_load_public: No such file or directory
    Could not load host key: /etc/ssh/ssh_host_rsa_key
    debug1: key_load_private: No such file or directory
    debug1: key_load_public: No such file or directory
    Could not load host key: /etc/ssh/ssh_host_dsa_key
    debug1: key_load_private: No such file or directory
    debug1: key_load_public: No such file or directory
    Could not load host key: /etc/ssh/ssh_host_ecdsa_key
    debug1: key_load_private: No such file or directory
    debug1: key_load_public: No such file or directory
    Could not load host key: /etc/ssh/ssh_host_ed25519_key
    

如果确实看到了此类消息,并且 /etc/ssh/ 下缺少主机密钥,则必须重新生成这些密钥,或者只是清除并安装 OpenSSH 服务器:

sudo apt-get purge openssh-server
sudo apt-get install openssh-server

在启用 WSL 可选功能后出现“找不到引用的程序集。”

此错误与处于错误的安装状态相关。 请完成以下步骤来尝试解决此问题:

  • 如果是从 PowerShell 运行了启用 WSL 功能的命令,请尝试改用 GUI,方法是打开“开始”菜单,搜索“启用或关闭 Windows 功能”,然后在列表中选择“适用于 Linux 的 Windows 子系统”,这将安装可选组件。

  • 转到“设置”、“更新”,然后单击“检查更新”来更新 Windows 版本

  • 如果这两个操作均失败,并且你需要访问 WSL,请考虑使用安装介质重新安装 Windows 并选择“保留所有内容”以确保保留你的应用和文件,从而就地升级。 可以在“重新安装 Windows 10”页面中找到有关如何执行此操作的说明。

如果看到此错误:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0777 for '/home/user/.ssh/private-key.pem' are too open.

若要解决此问题,请将以下内容追加到 /etc/wsl.conf 文件:

[automount]
enabled = true
options = metadata,uid=1000,gid=1000,umask=0022

请注意,添加此命令将包含元数据并修改有关从 WSL 中看到的 Windows 文件的文件权限。 有关详细信息,请参阅文件系统权限

无法通过在 Windows 上使用 OpenSSH 来远程使用 WSL

如果在 Windows 上使用 openssh-server 并尝试远程访问 WSL,则许多人会看到以下错误:

The file cannot be accessed by the system.

使用应用商店版本的 WSL 时,这是一个已知问题。 现在可以使用 WSL 1 或 Windows 内版本的 WSL 来暂时解决此问题。 有关详细信息,请参阅 https://aka.ms/wslstoreinfo

在分发中运行 Windows 命令失败

Microsoft Store 中提供的某些发行版尚不具备直接运行 Windows 命令的完全兼容性。 如果在运行 powershell.exe /c start . 或任何其他 Windows 命令时收到错误 -bash: powershell.exe: command not found,可按照以下步骤予以解决:

  1. 在 WSL 分发中运行 echo $PATH
    如果不包括:/mnt/c/Windows/system32,表示有什么重新定义了标准 PATH 变量。
  2. 使用 cat /etc/profile 检查配置文件设置。
    如果其中包含 PATH 变量的分配,则使用 # 字符来编辑文件,以注释掉 PATH 分配块。
  3. 检查 wsl.conf 是否存在 cat /etc/wsl.conf,并确保其中不包含 appendWindowsPath=false,否则请将其注释掉。
  4. 通过键入 wsl -t 后跟分发名称,或者在 cmd 或 PowerShell 中运行 wsl --shutdown 来重启分发。

安装 WSL 2 后无法启动

我们注意到用户在安装 WSL 2 后无法启动的问题。 我们对该问题进行了全面诊断,而用户报告称更改缓冲区大小安装适当的驱动程序可帮助解决此问题。 请查看此 GitHub 问题了解有关此问题的最新更新。

禁用 ICS 时出现 WSL 2 错误

Internet 连接共享 (ICS) 是 WSL 2 的必需组件。 主机网络服务 (HNS) 使用 ICS 服务来创建基础虚拟网络,WSL 2 依赖该网络来进行 NAT、DNS、DHCP 和主机连接共享。

禁用 ICS 服务 (SharedAccess) 或通过组策略禁用 ICS 会阻止创建 WSL HNS 网络。 这将导致在创建新的 WSL 版本 2 映像时失败,并在尝试将版本 1 映像转换为版本 2 时出现以下错误。

There are no more endpoints available from the endpoint mapper.

需要 WSL 2 的系统应将 ICS 服务 (SharedAccess) 保留在“手动(触发启动)”这一默认启动状态,并且应覆盖或删除禁用 ICS 的所有策略。 虽然禁用 ICS 服务会破坏 WSL 2,我们不建议禁用 ICS,但可以使用这些说明禁用 ICS 部分。

使用旧版 Windows 和 WSL

如果运行的是旧版 Windows 和 WSL,例如 Windows 10 创意者更新(2017 年 10 月的内部版本 16299)或周年更新(2016 年 8 月的内部版本 14393),则有几处差异需要注意。 建议更新到最新的 Windows 版本,但如果无法执行此操作,请了解下面概述的一些差异。

互操作性命令差异:

  • bash.exe 已替换为 wsl.exe。 可以从 Windows 命令提示或 PowerShell 运行 Linux 命令,但对于早期 Windows 版本,可能需要使用 bash 命令。 例如:C:\temp> bash -c "ls -la"。 传入 bash -c 的 WSL 命令将按原样转发到 WSL 进程。 必须以 WSL 格式指定文件路径,并且必须谨慎转义相关字符。 例如 C:\temp> bash -c "ls -la /proc/cpuinfo"C:\temp> bash -c "ls -la \"/mnt/c/Program Files\""
  • 若要查看哪些命令适用于特定的分发版,请运行 [distro.exe] /?。 举个使用 Ubuntu 的例子:C:\> ubuntu.exe /?
  • Windows 路径包含在 WSL $PATH 中。
  • 从早期的 Windows 10 版本中的 WSL 分发版调用 Windows 工具时,需要指定目录路径。 例如,若要通过 WSL 命令行调用 Windows 记事本应用,请输入:/mnt/c/Windows/System32/notepad.exe
  • 若要将默认用户更改为 root,请在 PowerShell 中使用此命令:C:\> lxrun /setdefaultuser root,然后运行 Bash.exe 登录:C:\> bash.exe。 使用发行版密码命令 ($ passwd username) 重置密码,然后关闭 Linux 命令行 ($ exit)。 在 Windows 命令提示符或 Powershell 中,将默认用户重置回常规的 Linux 用户帐户:C:\> lxrun.exe /setdefaultuser username

卸载旧版 WSL

如果最初在创意者更新(2017 年 10 月的内部版本 16299)前的某个 Windows 10 版本上安装了 WSL,我们建议你将任何必需的文件、数据等从安装的旧 Linux 发行版迁移到通过 Microsoft Store 安装的新发行版。 若要从计算机中删除旧发行版,请通过命令行或 PowerShell 实例运行以下命令:wsl --unregister Legacy。 还可以选择手动删除旧发行版,方法是使用 Windows 文件资源管理器或 PowerShell 删除 %localappdata%\lxss\ 文件夹(及其所有子内容):rm -Recurse $env:localappdata/lxss/