WSL与Windows网络栈共用:从NAT到mirrored的完整指南
2026/9/17 3:36:04 网站建设 项目流程

WSL 装好、开发环境弄完,最容易被忽略的就是网络这一层。很多人在 Windows 上跑 WSL 里的服务,以为两边天然就是"同一个网络",结果浏览器访问 localhost 就是不通,SSH 连不上,Docker 端口也映射不出去。这些问题的根源,在于 WSL 两个大版本在"网络栈"上的设计完全不同。这篇文章就把 WSL 与 Windows 共用网络栈这件事讲透,包括 WSL 1 的真共用、WSL 2 的 NAT 虚拟网卡、Windows 11 下的 mirrored 镜像网络,以及 VSCode、Docker、中间件、空间清理等实际场景里的网络问题。不管是刚接触 WSL 的小白,还是被端口转发折腾过的老手,这篇文章都能给到你直接能用的方案。

1. WSL 与 Windows 网络栈:先搞清楚架构再谈共用

很多教程说"WSL 和 Windows 共用网络栈",这话只说对了一半。它用来描述 WSL 1 是准确的,但到了 WSL 2,情况完全变了。要理解整个网络问题,得先明白 WSL 的两个版本在网络层面的架构差异。

1.1 WSL 1 的"真共用网络栈"

WSL 1 不是一个虚拟机,它是一个系统调用翻译层。你在 WSL 1 里敲的 Linux 命令,实际是翻译成 Windows 系统调用去执行的。因为进程本身跑在 Windows 内核之上,所以网络请求也是直接走 Windows 的网络栈。这意味着 WSL 1 里的网卡就是 Windows 的网卡,IP 就是 Windows 的 IP,没有虚拟交换机,没有 NAT,根本没有"两个网络"的边界。

这个设计带来一个非常舒服的体验:WSL 1 里起的服务,Windows 上直接 localhost 访问,反过来也一样,因为大家压根就在同一条网络链路上。对老开发者来说,这种感觉才是真正的"共用网络栈"。但代价也很明显,WSL 1 对 Linux 系统调用的兼容性有限,很多依赖内核特性的软件跑不起来,尤其是 Docker。

1.2 WSL 2 的"虚拟网络栈"

WSL 2 换了一套思路,它基于 Hyper-V 虚拟化技术,是一个轻量级虚拟机。既然是虚拟机,就有自己独立的内核和虚拟网卡。Windows 安装 WSL 2 之后,网络层会多出一个名叫 vEthernet (WSL) 的虚拟网卡,WSL 2 发行版里的 eth0 就是挂在它下面的。WSL 2 内部是一个 NAT(网络地址转换)网络,默认网段一般是 172.x.x.x 或者 192.168.x.x,这个地址和 Windows 主机的地址不在一个网段。

换句话说,WSL 2 是把 Windows 和 Linux 两个"网络栈"物理隔离了。这么做换来的好处是内核兼容性大幅提升,Docker、内核模块、CUDA 都能用上,但网络就变成了"NAT 加端口转发"这种绕来绕去的玩法。这也是绝大多数人遇到的网络问题的来源。

1.3 "共用网络栈"的新形态:Windows 11 的 mirrored 模式

微软后来也意识到 WSL 2 的 NAT 模式太绕了,于是在较新的 WSL 版本里加入了 mirrored 镜像网络模式。它做的事情可以理解成:把 WSL 2 的虚拟网络栈直接"镜像"到 Windows 主机的网络栈上。镜像模式下,WSL 里的 IP 地址和 Windows 是同一个,访问 localhost 从"转发"变成了真正的"本机访问",IPv6 也能正常用,体验接近 WSL 1 的随心所欲。

我在实际使用中强烈推荐 Windows 11 用户开启这个模式。配置方法非常简单,后面会详细展开。先记住一个结论:同样是"共用网络栈",WSL 1 是天然共用,mirrored 模式是技术实现上的共用,而 WSL 2 默认 NAT 模式则不是。理解了这一点,后面所有排查思路都会清晰很多。

对比项WSL 1WSL 2 默认 NATWSL 2 mirrored
内核无独立内核独立 Linux 内核独立 Linux 内核
网卡类型复用 Windows 网卡虚拟网卡 eth0共享 Windows 网卡地址
IP 地址同 Windows172.x 等 NAT 网段同 Windows
localhost 互通天然互通靠转发,有局限天然互通
Docker 支持不支持支持支持
适合场景轻量脚本、文件处理完整 Linux 开发环境网络敏感的生产级开发

2. 实操第一步:判断你当前用的是哪种网络形态

不管是要配置网络,还是要排查网络问题,第一步永远是确认自己当前用的是 WSL 1 还是 WSL 2,以及 WSL 2 当前是不是默认的 NAT 模式。这一步判断错,后面全白搭。

2.1 两条命令看清版本

打开 PowerShell 或者 CMD,运行下面的命令查看当前系统的 WSL 版本:

wsl -l -v

输出里会列出每个发行版的名字和版本号,比如:

NAME STATE VERSION * Ubuntu Running 2

VERSION 那一列是 2,就说明这个发行版跑在 WSL 2 上。你还可以进入 WSL 里执行uname -r看内核版本,如果输出里有microsoft-standard-WSL2字样,也说明是 WSL 2。

再看网络接口。进入 WSL 执行ip addr,如果看到 eth0 的地址是 172.x 或者 192.168.x 这种保留网段,说明当前处于 NAT 模式。如果看到网卡地址和 Windows 主机的 IP 一模一样,说明你可能已经开启了 mirrored 模式。

2.2 三组测试快速验证"共用"程度

光看版本还不够,我用三组测试帮你判断当前网络到底"共用"到了什么程度。

第一组:对比 IP。在 WSL 里执行hostname -I,在 Windows 的 CMD 里执行ipconfig。如果两者的地址完全一样,那就是 WSL 1 或 mirrored 模式;如果 WSL 里是 172 开头的地址,而 Windows 是其他地址,那就是 NAT 模式。

第二组:WSL 访问 Windows。在 WSL 里用 curl 访问 Windows 上的一个服务,比如curl http://localhost:8080。在 NAT 模式下,这里的 localhost 实际会通过转发机制落到 Windows 本身,所以也能通,但语义和 WSL 1 不一样。

第三组:Windows 访问 WSL。在 WSL 里跑一个简单的 HTTP 服务:

cd /tmp python3 -m http.server 8000

然后在 Windows 浏览器打开http://localhost:8000。能打开,说明 localhost 转发工作正常;打不开,说明你的 WSL 配置有问题,或者 WSL 里的服务没有监听在 0.0.0.0 上。

2.3 不同网络形态下的 IP 规律

这三组测试做完,你基本就知道自己处于什么状态了。我整理了不同形态下最容易观察到的 IP 规律:

  • WSL 1:没有 eth0 网卡的概念,网络请求全部复用 Windows 网络栈,IP 就是 Windows 的 IP,没有边界问题。
  • WSL 2 NAT:WSL 内 eth0 是独立的 172.x 网段,Windows 侧会有一个 vEthernet (WSL) 网卡,也是 172.x 网段,两边通过虚拟交换机通信。这个网段每次重启大概率会变。
  • WSL 2 mirrored:WSL 里 eth0 的 IP 和 Windows 一致。注意,这里网卡仍然是虚拟的,但地址和 Windows 相同,所以看起来就像共用一张网卡。

记住这些特征,后面配置端口转发、设置防火墙规则的时候,心里就有数了。

3. WSL 2 NAT 网络栈的细节与坑

既然 WSL 2 默认 NAT 模式是用户量最大的场景,那它的网络细节就值得花一整章来讲。很多人在这里踩坑,是因为不理解 NAT 模式下的几个关键机制:虚拟网卡、localhost 转发、防火墙,以及端口保留。

3.1 vEthernet (WSL) 网卡与 Hyper-V 虚拟交换机

当你安装 WSL 2 并启用虚拟机平台后,Windows 会自动创建一个虚拟网卡 vEthernet (WSL)。这个网卡不是普通的回环设备,它本质上连接着一个内置的 NAT 交换机。WSL 2 发行版里的 eth0 就是通过这个虚拟交换机接入 NAT 的。

可以这么理解:Windows 主机相当于家里面的路由器,WSL 2 相当于路由器下面的一台电脑。这台电脑的 IP 是由 NAT 的 DHCP 分配的,通常是 172.x 网段,路由器(Windows)会负责把对外流量做一个地址转换。所以外部世界里只有 Windows 这个"路由器"的地址,WSL 2 的地址只在内部可见。

这也是为什么 WSL 2 里的 IP 地址每次冷启动都不一样。它是动态分配的,不像物理网卡那样有固定地址。这一点在写自动化脚本、配置端口转发的时候特别要小心,写死 IP 是最容易踩的坑。

3.2 localhost 转发是怎么工作的

WSL 2 在 NAT 模式下有一个很贴心的机制:当 Windows 上的程序访问 localhost 的某个端口时,WSL 2 有一个转发组件(wslrelay)会把流量转发到 WSL 里监听该端口的服务。这就是为什么你在 WSL 里跑python3 -m http.server 8000,Windows 浏览器访问 localhost:8000 能通的原因。

这个机制的本意是模拟 WSL 1 的无缝体验,但它有几个限制:第一,只对 TCP 协议友好,UDP 转发基本不工作;第二,只有当 WSL 进程监听的是 0.0.0.0 或者::这种通配地址时才生效,如果服务只绑定了 127.0.0.1,Windows 的 localhost 是转发不过去的;第三,如果 Windows 端口已经被其他程序占用,转发也会失败。

这就是为什么很多人说"WSL 里 Redis 启动成功但 Windows 连不上"。常见配置下 Redis 默认绑定 127.0.0.1,监听地址不是通配地址,localhost 转发自然不生效。解决思路我后面章节会详细展开。

3.3 NAT 模式下 Windows 与 WSL 互访的规律

搞清楚转发机制还不够,你得掌握 NAT 模式下两个方向访问的规律。我把这几年的使用经验浓缩成一张表,照着做基本不会出错。

访问方向目标地址说明
WSL → WindowsWindows 主机 IPip route show default查默认网关,或读 /etc/resolv.conf 里的 nameserver
WSL → Windowslocalhost部分场景有效,建议直接用网关心态访问
Windows → WSLWSL 内网 IP先用hostname -I查地址,但 IP 会变
Windows → WSLlocalhost依赖 localhost 转发,只对通配监听地址有效
局域网设备 → WSLWindows IP + 端口需要 netsh 端口转发

这里还有一个很容易忽略的点:Windows 防火墙。NAT 模式下,Windows 的防火墙默认会拦截来自虚拟交换机方向的入站连接。如果你在 Windows 上访问 WSL 的 172.x 地址失败,先别急着查 WSL 里的服务,看看 Windows 防火墙的入站规则是不是把这条流量掐了。放行方式我在后面章节专门写。

3.4 端口冲突与保留端口

NAT 模式下还有一个非常诡异的问题:明明端口没被占用,但服务就是绑定失败。这在 Windows 上装了 Docker Desktop、开启 Hyper-V 的机器上尤其常见。

原因是 Hyper-V 会保留一段动态端口范围。Windows 在分配临时端口时,会锁定这段范围,避免和其他系统服务冲突。你可以用下面的命令查看当前被排除了哪些端口:

netsh interface ipv4 show excludedportrange protocol=tcp

如果输出里有一段范围包含你想用的端口,那你在这个端口上绑定监听就会失败,提示"端口被占用",但实际查不到任何进程占用。解决办法很简单:避开这段保留范围,换一个端口;或者重启 Windows 后,在系统还没完全占用这些端口前赶紧绑定服务,但这个方法不推荐,太不稳定。遇到这种情况,换端口是最省心的。

4. 配置方案:让 WSL 网络真正"接近共用"

理解了 NAT 模式的原理,接下来就可以动手配置了。这一章我给出四套方案,覆盖不同系统、不同需求的场景。目标是让 WSL 的网络尽可能"像共用网络栈"一样顺手。

4.1 版本切换:什么时候用 WSL 1,什么时候用 WSL 2

如果你真的需要"网络完全透明"的体验,可以在特定发行版上切换到 WSL 1。这个操作很简单:

# 把名为 Ubuntu 的发行版切到 WSL 1 wsl --set-version Ubuntu 1 # 切回 WSL 2 wsl --set-version Ubuntu 2 # 设置默认新安装发行版使用哪个版本 wsl --set-default-version 2

什么时候用 WSL 1?我的经验是:当你主要做脚本工具类工作、处理 Windows 文件系统的文件、对 Linux 内核特性没有需求时,WSL 1 反而更舒服。它在 /mnt/c 这类 Windows 挂载路径上的 IO 性能优于 WSL 2,网络又是天然的"共用栈",省掉很多转发问题。而且 WSL 1 可以运行在 FAT32 格式的 U 盘上,这是 WSL 2 做不到的。

什么时候必须用 WSL 2?要跑 Docker、要用 CUDA、要装内核模块、要跑依赖完整 Linux 内核的程序,那就别犹豫,切到 WSL 2 并做好网络配置。

注意:切换版本是一个转换文件系统的过程,期间会重新打包整个发行版,耗时可能很长,几十 GB 的发行版转起来要等很久。转换过程不要强制中断,也别关机,否则发行版容易损坏。操作前最好先备份重要数据。

4.2 Windows 11 mirrored 模式配置

如果你用的是 Windows 11,并且 WSL 版本比较新(2.0.0 以上),我非常推荐直接开启 mirrored 网络模式。这一步做完,NAT 模式下那些 localhost 转发、端口冲突、IPv6 不支持的问题会消失大半。

配置文件在C:\Users\<你的用户名>\.wslconfig,如果没有就手动创建一个,内容如下:

[wsl2] networkingMode=mirrored dnsTunneling=true firewall=true autoProxy=true

配置说明:

  • networkingMode=mirrored:开启镜像网络,核心选项。
  • dnsTunneling=true:把 WSL 里的 DNS 请求通过隧道发送到 Windows 的 DNS 服务,能解决 DNS 解析的很多怪问题。
  • firewall=true:让 Windows 防火墙规则对 WSL 生效,避免 WSL 流量绕过防火墙的尴尬情况。
  • autoProxy=true:如果 Windows 配置了 HTTP 代理,WSL 会自动继承代理设置,省掉手动 export。

改完配置后,在 PowerShell 里执行:

wsl --shutdown

然后再进入 WSL,执行ip addr。你会看到 eth0 的地址已经变成和 Windows 主机一样了。这时候 WSL 里监听 8080 端口,Windows 访问 localhost:8080 就是真的"本机访问",不再是转发。

有一点要注意:mirrored 模式下,Linux 和 Windows 共享同一套网络栈,意味着它们不能同时监听同一个端口。这和 NAT 模式不同,NAT 模式下两边各自有网卡,绑同样的端口不冲突。这是"共用网络栈"的必然结果,习惯就好。

4.3 解决 DNS 问题

DNS 问题在 NAT 模式下尤其常见。表现是:WSL 里apt update很慢甚至超时,curl 外网域名解析失败,但 ping IP 地址又是通的。这些基本都是 DNS 配置出了问题。

NAT 模式下,WSL 会自动生成/etc/resolv.conf,里面通常会写上 Windows 虚拟网卡的 IP 作为 nameserver。这个模式大部分时间是正常的,但一旦 Windows 网络环境变化(比如换了 WiFi、公司网和家庭网切换),这个地址就会失效或者变得很慢。

手动解决分两步。第一步,进入 WSL 修改 /etc/resolv.conf:

sudo nano /etc/resolv.conf

写上你信任的 DNS 服务器,比如:

nameserver 223.5.5.5 nameserver 8.8.8.8

第二步,防止 WSL 重启后自动覆盖这个文件。创建或编辑 /etc/wsl.conf:

sudo nano /etc/wsl.conf

加入:

[network] generateResolvConf = false

改完后wsl --shutdown重启一次。以后如果你需要恢复自动生成的 resolv.conf,只要把 generateResolvConf 改回 true,重启即可。

4.4 代理环境配置

很多人需要在公司内网环境里用 WSL,访问外网要经过一个 HTTP 代理服务器。这个需求完全可以配置,和任何敏感话题无关,纯粹是标准的 Linux 代理设置。

在 NAT 模式下,WSL 访问 Windows 上监听的代理服务,不能用 localhost,要用 Windows 的 IP。可以动态获取:

export HOST_IP=$(ip route show default | awk '{print $3}') export http_proxy="http://$HOST_IP:端口号" export https_proxy="http://$HOST_IP:端口号"

但这样每次进入终端都要执行一次。更省事的做法是把它写进 ~/.bashrc:

echo 'export HOST_IP=$(ip route show default | awk "{print \$3}")' >> ~/.bashrc echo 'export http_proxy="http://$HOST_IP:7890"' >> ~/.bashrc echo 'export https_proxy="http://$HOST_IP:7890"' >> ~/.bashrc source ~/.bashrc

在 WSL 里测试一下:

curl -I https://example.com

能返回响应头说明代理通了。注意,端口号要替换成你自己内网代理实际监听的端口,别照抄。

如果你开了 mirrored 模式,这个配置更简单。因为 WSL 和 Windows 共享网络栈,代理服务如果监听在 Windows 的 127.0.0.1 上,WSL 里直接设置 127.0.0.1 就能访问到:

export http_proxy="http://127.0.0.1:7890" export https_proxy="http://127.0.0.1:7890"

4.5 端口转发:NAT 模式下的"共用"补丁

如果你还在用 NAT 模式,又希望局域网里其他设备能访问 WSL 里的服务,那就需要用到 Windows 的端口转发功能。这一步相当于在你家路由器上做一个端口映射,把 Windows 的某个端口转发到 WSL 2 内部的某个端口。

先在 WSL 里拿到当前 IP:

hostname -I | awk '{print $1}'

假设是 172.20.10.5,你想把 WSL 里的 8080 端口暴露到 Windows 的 8080 端口,以管理员身份打开 PowerShell:

netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=8080 connectaddress=172.20.10.5

然后放行 Windows 防火墙:

netsh advfirewall firewall add rule name="WSL Port 8080" dir=in action=allow protocol=TCP localport=8080

这样局域网里的其他设备就可以通过http://Windows主机IP:8080访问到 WSL 里的服务了。

但这里有个大坑:172.20.10.5 是动态的,重启后大概率会变。端口转发规则里写死的 IP 就失效了。我的习惯是写一个 PowerShell 脚本,放到开机启动里,每次启动时自动获取 WSL 当前 IP 并重新配置转发规则。

$wslIp = (wsl hostname -I).Trim().Split(' ')[0] netsh interface portproxy delete v4tov4 listenport=8080 listenaddress=0.0.0.0 netsh interface portproxy add v4tov4 listenport=8080 listenaddress=0.0.0.0 connectport=8080 connectaddress=$wslIp
> 提示:netsh 的 portproxy 重名规则会覆盖同名条目,但 IP 变了之后旧的映射并不会自动更新,所以必须每次先删除再添加。

说实话,如果你经常需要这个功能,最简单的方案还是升级到 mirrored 模式或直接用 WSL 1。端口转发更适合临时救急,长期依赖它就是一种自虐。

5. 真实场景下的网络栈表现

前面讲的是原理和配置,这一章把范围放宽到几个真实场景,看看 WSL 网络栈在各种常见工具链里的实际表现。这些场景我在日常开发里都反复遇过。

5.1 VSCode 连 WSL 为什么不需要配网络

细心的朋友会发现一个问题:用 VSCode 的 Remote-WSL 扩展连接 WSL 时,从来没让人配置过 IP、端口这些东西,连接过程始终稳定。为什么?

因为 VSCode 连接 WSL 根本不走 IP 网络。它走的是 WSL 的一个内部通道,通过名为 wsl.exe 的进程和 Linux 侧的 unix socket 通信。具体机制可以理解成:VSCode 通过 Windows API 启动了 wsl.exe,wsl.exe 进入 WSL 环境后,在 /tmp 下面创建了一个 unix socket 文件,然后 VSCode 通过这个 socket 和 WSL 里的 vscode-server 通信。

这个链路绕开了网卡、IP、端口,完全由 WSL 的进程管理器直接控制。所以不管你的 WSL 是 1 还是 2,NAT 还是 mirrored,VSCode 的体验几乎一模一样。这也解释了为什么很多人 WSL 网络配置混乱,但 VSCode 里写代码毫无影响。

5.2 Docker Desktop 的 WSL2 后端

Docker Desktop 在 Windows 上使用 WSL 2 后端时,会额外创建一个 WSL 发行版,通常叫 docker-desktop。Docker 守护进程就跑在这个特殊发行版里,用户自己的发行版则作为客户端连接到这个守护进程。

容器端口的暴露链路是这样的:容器映射端口 → docker-desktop 发行版内的 NAT → WSL 网卡 → Windows 的 localhost 转发 → 从 Windows 访问。因为 Docker Desktop 自动处理了这整条链路,所以你在 Windows 上直接 localhost:映射端口 就能访问容器服务,感觉非常顺滑。

但如果你不是在 Docker Desktop 里跑 Docker,而是在 WSL 里自己装了 docker-ce,那端口映射就需要自己操心。容器发布了一个端口,它只暴露在 WSL 的 NAT 网络里,Windows 上访问 localhost 可能会失效。这种情况的处理方式和前面 NAT 模式互访的规律一致,看表照做就行。

5.3 中间件在 WSL 里的网络表现

很多人喜欢把 Elasticsearch、Redis、MySQL 这些中间件装在 WSL 里,方便又干净。但不同中间件对监听地址的默认行为不一样,直接影响 Windows 端访问。

以 Elasticsearch 为例,它默认监听 0.0.0.0:9200,也就是通配所有网卡。在 WSL 2 NAT 模式下,Windows 访问 localhost:9200 可以成功,因为转发机制找到了通配监听。

但 Redis 不一样。Redis 默认监听 127.0.0.1:6379,只允许本机回环访问。在 NAT 模式下,Windows 访问 WSL 的 6379 会失败。改进方法:

sudo nano /etc/redis/redis.conf

把 bind 行改掉:

# 原配置 bind 127.0.0.1 -::1 # 开发环境改为 bind 0.0.0.0

同时把 protected-mode 改成 no,方便局域网联调。注意,这仅限开发环境,生产环境千万别这么干。

MySQL 默认也是只监听 127.0.0.1,需要修改/etc/mysql/mysql.conf.d/mysqld.cnf里的 bind-address:

bind-address = 0.0.0.0

改完重启服务。要注意,监听 0.0.0.0 之后,服务会暴露在整个 NAT 网络里。如果你是在公司内网,建议配合防火墙限制访问来源,不要裸奔。

5.4 WSL 里跑 binwalk 拆固件这类工具

如果你的工作涉及固件分析,binwalk 这种 Linux 生态工具在 WSL 里跑会非常顺手。这类工具对网络几乎没有依赖,真正要注意的是文件路径和 IO 性能。

WSL 访问 Windows 文件的路径是 /mnt/c/...,访问速度在 WSL 2 下明显慢于原生 Linux 文件系统。我的建议是:把要分析的固件先复制到 WSL 的文件系统里,比如 ~/work/,然后再跑 binwalk。这样 IO 不会成为瓶颈,解包、识别文件系统都更快。

这个场景其实说明了一个问题:并不是所有任务都需要"共用网络栈"。工具链的可用性、生态优势往往比网络形态更重要。分清任务需求,才能选择最合适的 WSL 版本和网络模式。

5.5 CUDA 训练与多机通信场景

WSL 2 通过 GPU 直通支持 CUDA,深度学习训练在 WSL 里已经非常常见。GPU 的计算路径走的是专门的 /dev/dxg 设备,不经过网络栈,所以网络模式对单卡训练几乎没影响。

但如果要做分布式训练,多台机器之间的通信就需要走网络。NAT 模式下,WSL 的 IP 在虚拟网络里,外部机器直接访问不进来,这时候必须靠 netsh 端口转发,或者干脆换 mirrored 模式。镜像模式下,WSL 和 Windows 共用网络栈和 IP,分布式训练的网络通信会顺畅很多。

我个人的实践是:凡是涉及多机通信的任务,优先考虑 mirrored 模式;如果因为某些原因不能用 mirrored,那就把端口转发脚本写好再开工。

6. 常见问题与排查技巧实录

最后这一章给大家整理几个我实际踩过、也帮朋友排查过的高频问题。这些问题在网上被反复问,但很少有人给出一个完整、可落地的解决方案。

6.1 wsl --install 太慢 / wsl --update 下载很慢

这是国内用户问得最多的问题。wsl --install会从微软服务器拉取组件,wsl --update会下载内核更新包,这些请求在有些网络环境里非常慢。

我试过的最有效方案是这样的:

第一种,清理 Windows 应用商店缓存。因为 wsl --install 走的是微软商店的交付渠道,缓存坏了会严重影响下载速度。

wsreset.exe

执行完它会自动关闭商店并清缓存,然后再试一次安装。

第二种,手动下载发行版离线安装包。这是最稳妥的方案,不依赖商店的下载通道。去微软的 WSL 发行版下载页面,找到你需要的发行版的 .appx 文件下载,下载完成以后用 PowerShell 执行:

Add-AppxPackage .\Ubuntu2204.appx

安装完成后,从开始菜单启动一次,设置用户名密码,然后执行wsl --update更新内核。如果内核更新还是慢,可以单独下载 WSL 内核安装包离线安装,同样能绕过网络问题。

第三种,换个时间段。这条路有点玄学,但确实有效。国内访问微软服务器,白天经常慢到难以忍受,深夜时段偶尔会快很多。如果前面的方法都试过不行,可以晚上再试一次wsl --update

6.2 WSL 删除文件后空间不释放

WSL 2 的文件系统存储在一个 ext4.vhdx 虚拟磁盘文件里。这个文件的一个特点是:只增不减。你往里面写入大量数据,它会膨胀;你把数据删掉,它却不会自动收缩。这就是为什么很多人发现 WSL 里空间已经释放了,但 Windows 的 C 盘还是那么大。

解决方法是手动压缩虚拟磁盘。第一步:

wsl --shutdown

第二步,在管理员 PowerShell 里用 diskpart 压缩。

diskpart select vdisk file="C:\Users\<你的用户名>\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu*\LocalState\ext4.vhdx" attach vdisk readonly compact vdisk detach vdisk exit

路径里的CanonicalGroupLimited.Ubuntu*会因发行版不同而不同,比如 Ubuntu 的目录名就是这个模式。如果不确定路径,可以搜索 ext4.vhdx 找到它。

压缩完成后,C 盘空间会释放不少。不过要注意,压缩需要 Windows 能独占这个文件,所以执行前必须 wsl --shutdown。如果还开着其他依赖 WSL 的进程,比如 Docker Desktop,也一并关掉。

6.3 识别不到 WSL:MATLAB 以及其他老软件

有些软件,比如 MATLAB 的某些版本,原生支持调用 WSL 作为 Linux 环境。但经常有人遇到软件识别不到 WSL 的情况。

排查思路有这么几步。第一,确认 WSL 版本在 Windows 10 2004 以上,版本太老很多软件不认识 wsl.exe 的现代参数。第二,检查 wsl.exe 是否在系统 PATH 里。在 CMD 里执行:

where wsl

正常情况下应该返回C:\Windows\System32\wsl.exe。如果没有,说明系统 PATH 异常,手动把 System32 加回 PATH。第三,确认当前 WSL 发行版用的是 WSL 2,不少软件是只认 WSL 2 的。

MATLAB 场景还有一个特殊点:它调用 WSL 时不走网络,而是直接在本地调用 wsl.exe 执行命令。所以"识别不到 WSL"基本都是路径、版本、发行版状态的问题,和网络配置无关。检查完上面三条,百分之九十的情况都能解决。

6.4 端口被保留/占用导致服务无法绑定

前面提到 Hyper-V 会保留一段端口范围,这里再展开说一个我在 Docker 场景里遇到的典型问题。

你在 Windows 上装了 Docker Desktop,同时在 WSL 里自己装了一个服务,想监听某个端口,比如 3000。结果服务一直报端口被占用,但netstat -ano | findstr 3000查不到任何进程。

这个就是 Hyper-V 的保留端口范围在不断变化造成的。每次 Windows 启动,某些系统服务会动态申请端口段,被申请的段会被标记为排除。你查一下:

netsh interface ipv4 show excludedportrange protocol=tcp

如果 3000 落在某个排除范围里,那就只能换端口。网上有说法可以通过调整动态端口范围来规避,但实际操作会影响其他系统服务,不推荐在没有把握的情况下乱改。换一个端口是成本最低的方案。

6.5 文件系统 IO 慢,在 /mnt/c 下跑项目尤其明显

这个问题虽然不完全是网络,但和"共用"这个概念很相关。WSL 2 访问 Windows 文件挂载路径(/mnt/c)时的跨系统文件操作非常慢,尤其是在 /mnt/c 下跑 node_modules 依赖、编译、打包,慢到怀疑人生。

原因是 WSL 2 访问 Windows 文件系统要走 9P 协议,这个协议的额外开销很大,文件越多、路径越深越明显。我之前在 /mnt/c 的一个项目目录下跑前端构建,动辄要两三分钟,把项目复制到 WSL 自己的文件系统 ~/projects/ 下,同样的构建二三十秒就完了,差距非常悬殊。

不过大多数人不喜欢把代码放 WSL 里,担心 Windows 里其他工具访问不到。折中方案是:代码依然放在 Windows 目录里,但把 node_modules、构建缓存这类 IO 密集的目录建立符号链接,指到 WSL 的文件系统。这样两边都能访问,速度也不至于太慢。

写在最后

再分享一个小技巧:如果你经常要在 WSL 和 Windows 之间切换网络环境(比如家里、公司、公共场所),建议把网络相关的配置用一个脚本统一管理,不要散落在 .bashrc、.wslconfig、netsh 命令里。我在 .bashrc 里就放了一个切换函数,按不同场景一键设置 DNS、host IP 和代理变量。遇到问题第一件事不是重新配置,而是先判断当前的网络形态,再决定走哪条排查路线。

WSL 的网络问题不复杂,复杂的是没有把原理搞清楚就开始瞎配置。希望这篇文章能让你对整个"共用网络栈"的概念有一个清晰的把握,下次再遇到 localhost 不通、端口映射失败这类问题,能直接对症下药。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询