尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

WSL与Windows网络栈共用:从NAT到mirrored的完整指南

WSL与Windows网络栈共用:从NAT到mirrored的完整指南 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 网段同 Windowslocalhost 互通天然互通靠转发有局限天然互通Docker 支持不支持支持支持适合场景轻量脚本、文件处理完整 Linux 开发环境网络敏感的生产级开发2. 实操第一步判断你当前用的是哪种网络形态不管是要配置网络还是要排查网络问题第一步永远是确认自己当前用的是 WSL 1 还是 WSL 2以及 WSL 2 当前是不是默认的 NAT 模式。这一步判断错后面全白搭。2.1 两条命令看清版本打开 PowerShell 或者 CMD运行下面的命令查看当前系统的 WSL 版本wsl -l -v输出里会列出每个发行版的名字和版本号比如NAME STATE VERSION * Ubuntu Running 2VERSION 那一列是 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 NATWSL 内 eth0 是独立的 172.x 网段Windows 侧会有一个 vEthernet (WSL) 网卡也是 172.x 网段两边通过虚拟交换机通信。这个网段每次重启大概率会变。WSL 2 mirroredWSL 里 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 8000Windows 浏览器访问 localhost:8000 能通的原因。这个机制的本意是模拟 WSL 1 的无缝体验但它有几个限制第一只对 TCP 协议友好UDP 转发基本不工作第二只有当 WSL 进程监听的是 0.0.0.0 或者::这种通配地址时才生效如果服务只绑定了 127.0.0.1Windows 的 localhost 是转发不过去的第三如果 Windows 端口已经被其他程序占用转发也会失败。这就是为什么很多人说WSL 里 Redis 启动成功但 Windows 连不上。常见配置下 Redis 默认绑定 127.0.0.1监听地址不是通配地址localhost 转发自然不生效。解决思路我后面章节会详细展开。3.3 NAT 模式下 Windows 与 WSL 互访的规律搞清楚转发机制还不够你得掌握 NAT 模式下两个方向访问的规律。我把这几年的使用经验浓缩成一张表照着做基本不会出错。访问方向目标地址说明WSL → WindowsWindows 主机 IP用ip route show default查默认网关或读 /etc/resolv.conf 里的 nameserverWSL → 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 protocoltcp如果输出里有一段范围包含你想用的端口那你在这个端口上绑定监听就会失败提示端口被占用但实际查不到任何进程占用。解决办法很简单避开这段保留范围换一个端口或者重启 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] networkingModemirrored dnsTunnelingtrue firewalltrue autoProxytrue配置说明networkingModemirrored开启镜像网络核心选项。dnsTunnelingtrue把 WSL 里的 DNS 请求通过隧道发送到 Windows 的 DNS 服务能解决 DNS 解析的很多怪问题。firewalltrue让 Windows 防火墙规则对 WSL 生效避免 WSL 流量绕过防火墙的尴尬情况。autoProxytrue如果 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.confsudo nano /etc/resolv.conf写上你信任的 DNS 服务器比如nameserver 223.5.5.5 nameserver 8.8.8.8第二步防止 WSL 重启后自动覆盖这个文件。创建或编辑 /etc/wsl.confsudo 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_proxyhttp://$HOST_IP:端口号 export https_proxyhttp://$HOST_IP:端口号但这样每次进入终端都要执行一次。更省事的做法是把它写进 ~/.bashrcecho export HOST_IP$(ip route show default | awk {print \$3}) ~/.bashrc echo export http_proxyhttp://$HOST_IP:7890 ~/.bashrc echo export https_proxyhttp://$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_proxyhttp://127.0.0.1:7890 export https_proxyhttp://127.0.0.1:78904.5 端口转发NAT 模式下的共用补丁如果你还在用 NAT 模式又希望局域网里其他设备能访问 WSL 里的服务那就需要用到 Windows 的端口转发功能。这一步相当于在你家路由器上做一个端口映射把 Windows 的某个端口转发到 WSL 2 内部的某个端口。先在 WSL 里拿到当前 IPhostname -I | awk {print $1}假设是 172.20.10.5你想把 WSL 里的 8080 端口暴露到 Windows 的 8080 端口以管理员身份打开 PowerShellnetsh interface portproxy add v4tov4 listenport8080 listenaddress0.0.0.0 connectport8080 connectaddress172.20.10.5然后放行 Windows 防火墙netsh advfirewall firewall add rule nameWSL Port 8080 dirin actionallow protocolTCP localport8080这样局域网里的其他设备就可以通过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 listenport8080 listenaddress0.0.0.0 netsh interface portproxy add v4tov4 listenport8080 listenaddress0.0.0.0 connectport8080 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.exewsl.exe 进入 WSL 环境后在 /tmp 下面创建了一个 unix socket 文件然后 VSCode 通过这个 socket 和 WSL 里的 vscode-server 通信。这个链路绕开了网卡、IP、端口完全由 WSL 的进程管理器直接控制。所以不管你的 WSL 是 1 还是 2NAT 还是 mirroredVSCode 的体验几乎一模一样。这也解释了为什么很多人 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-addressbind-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 fileC:\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 识别不到 WSLMATLAB 以及其他老软件有些软件比如 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 protocoltcp如果 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 不通、端口映射失败这类问题能直接对症下药。
返回列表