拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

WSL2从安装到开发环境:403、迁移D盘、内存与工具链

WSL2从安装到开发环境:403、迁移D盘、内存与工具链

我到现在还记得第一次在同事机器上敲下wsl --install之后那个转圈的终端——十分钟过去,进度条一动不动,最后蹦出来一行ERROR: 0x80072ee2。类似的事后来反复上演:有人卡在《正在安装: Ubuntu》那一步,有人拿到 403,有人装完发现 C 盘少了 30 个 G,还有人 Docker Desktop 开着开着弹一句 "your version of windows subsystem for linux (wsl) is too old"。WSL 本身不难,难的是它把 Windows 系统组件、虚拟化平台、微软的内容分发、Linux 发行版包管理这几套完全不同的东西缝在一起,任何一环出问题,表面上的报错都长得差不多。

这篇东西我想把 WSL 从"能开起来"到"能当日常开发环境用"这条路走一遍。包含咱们最常见的那些坑:wsl --install太慢甚至报 403、想把 Ubuntu 从 C 盘挪走、内存被 Vmmem 吃光、怎么在 VSCode 里用它、Docker Desktop 和 CUDA 的边界在哪、PyCharm 和 MATLAB 为什么认不出里面的解释器、binwalk 装出来怎么是老版本。不管你是完全没碰过的 Windows 用户,还是已经装了但总觉得别扭的开发者,应该都能从这里挑到能直接抄的部分。

1. 从一次卡死的 wsl --install 说起:这套东西到底解决什么问题

1.1 WSL 不是虚拟机,也不是双系统

很多人第一次听说 WSL,会下意识把它理解成"Windows 里装了个虚拟机"。这个类比有一半对,一半会害了你。WSL2 确实跑在轻量级虚拟化之上(Hyper-V 的那套底层),但它跟你在 VMware 里装一台 Ubuntu 完全是两回事:没有 BIOS 自检,没有完整的内核启动流程,内存是动态借的而不是开机就划走 8 个 G,文件系统通过一层专门设计的协议和 Windows 互通,进程可以直接互相看到。

关键差异在于"边界感"。虚拟机是一个黑盒子,你在里面干什么外面都不知道,得靠共享文件夹和端口转发;WSL 是一个和 Windows 高度耦合的子系统,你的\\wsl$路径能在资源管理器里直接打开,WSL 里的 8080 端口在 Windows 浏览器里直接就能访问,甚至能在 WSL 里调用explorer.exe打开 Windows 的窗口。我见过不少人装了 VMware 里一台 Ubuntu,然后抱怨"文件来回拷太麻烦"——那其实是他选错了工具。如果你只是想有个 Linux 命令行跑跑脚本、装装依赖、跑跑容器,WSL 的体验会好出一个数量级。

1.2 WSL1 和 WSL2 到底该选哪个

这是个到现在还有人问的问题。简单说结论:除了极少数场景,都该用 WSL2。

WSL1 走的是"系统调用翻译"路线,把 Linux 的系统调用实时翻译成 Windows 的,好处是启动快、和 Windows 文件系统同一份、跨系统访问几乎没损耗。坏处也明显:兼容性差,Docker 跑不了,fork这类调用性能惨不忍睹,很多需要内核特性的工具直接挂掉。WSL2 换成了真正的 Linux 内核跑在轻量虚拟机里,兼容性问题基本消失,Docker、systemd、CUDA 这些都能整。

代价是跨文件系统的 IO 变慢。这也是很多人吐槽"WSL 里跑 npm install 慢得要死"的原因——不是 WSL 慢,是你的项目放在了/mnt/c/Users/...下面。Linux 侧的文件在虚拟磁盘(ext4)里,Windows 侧的文件要通过 9p 协议转发,元数据操作(大量小文件的 stat、open、close)走这条协议开销巨大。

我做过一个粗略的对比,同一个前端项目,npm install:

项目位置耗时(同一台机器,多次取中位数)
/mnt/c/projects/app(Windows 盘)约 4 分 30 秒
/home/me/projects/app(WSL 盘)约 45 秒

差别接近六倍。所以从第一天起就养成习惯:代码放/home,只把需要和 Windows 共享的东西放/mnt/c。

1.3 哪些人真的需要它,哪些人不需要

需要:做后端和运维、要用 Docker 但主力机是 Windows、要跑各种 Linux 工具链(编译工具、嵌入式、安全分析)、要学 Linux 但不想折腾双系统的人。

不太需要:纯 Windows 桌面应用开发、只写写 Office 脚本、对命令行完全不感冒的人。硬装一个最后只会变成一个占着十几 G 的摆设。

还有个中间态也不少:有人只是想在 Windows 上跑个 Python 脚本,结果被劝去装 WSL。这种情况其实装个 Windows 原生 Python 就完了,没必要为了跑个requests引入一整套虚拟化。

2. 开启功能这一步:从"零状态"到能敲命令

2.1 三条安装路径,先想清楚走哪条

市面上的教程基本就是三种:

  1. 命令行一把梭:wsl --install,Windows 10 2004+ / Windows 11 默认可用,自动开组件、下内核、装默认发行版(Ubuntu)。
  2. 图形界面手动开:控制面板 → 程序和功能 → 启用或关闭 Windows 功能,勾选"适用于 Linux 的 Windows 子系统"和"虚拟机平台",重启后去商店装发行版。
  3. 手动下载分发包导入:完全绕开在线下载,适合网络受限、或者要装特定版本的情况。

选哪条取决于你的网络环境和系统版本。如果你的机器能顺畅访问微软的分发服务,第一条最省事;如果是企业内网、代理环境复杂、或者你已经被 403 折磨过,直接走第三条,别在第一条上浪费时间。

2.2 图形界面开启的完整操作

打开"控制面板"→"程序和功能"→左侧"启用或关闭 Windows 功能",会看到一个列表。你需要勾的通常有两项:

  • 适用于 Linux 的 Windows 子系统
  • 虚拟机平台(Virtual Machine Platform)

如果你打算在 WSL 里跑 Docker、或者用 WSL2 而不是 WSL1,"虚拟机平台"是必须的。有些老版本还需要勾"Hyper-V",但 Windows 11 家庭版没有 Hyper-V,也不影响 WSL2 使用——WSL2 用的是 Hyper-V 的一个子集,不依赖完整的 Hyper-V 角色。

勾完点确定,等系统应用更改,然后一定要重启。我见过有人在没重启的情况下就急着敲命令,然后对着"找不到 wsl 命令"发呆。组件注册是在重启阶段完成的,提前敲命令没有任何意义。

重启之后,用管理员权限打开 PowerShell,跑一句:

wsl --status

如果能看到默认分发版、内核版本、WSL 版本这些信息,说明底层通了。如果提示命令不存在,回去检查组件是不是真的勾上了。

2.3 命令行开启与版本要求对照

wsl --install这个命令不是所有 Windows 版本都支持,它在 Windows 10 2004 之前是不存在的。这也是很多人复制粘贴到老系统上没反应的原因。

Windows 版本wsl --install 支持需要手动开组件备注
Windows 10 1909 及更早不支持是只能手动开组件 + 商店装
Windows 10 2004 / 20H2 / 21H1支持一般自动部分版本仍需手动开虚拟机平台
Windows 10 21H2 / 22H2支持自动体验比较完整
Windows 11 全系支持自动默认 WSL2,支持--location等新参数
Windows 10 LTSC / 企业长期版视具体版本可能需手动组件包经常被精简化,需要单独确认

如果你的公司用的是长期服务版(LTSC),先别急着照网上的教程操作,很可能组件是被裁剪过的。可以在 PowerShell 里跑Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux看状态是 Enabled 还是 Disabled,Disabled 的话用Enable-WindowsOptionalFeature打开,比图形界面更明确。

3. wsl --install 太慢、403、超时的完整排查链路

3.1 先分清卡在哪个阶段

wsl --install这个命令其实内部干了好几件事,每件事失败的表现完全不同。搞清楚卡在哪一步,能省掉一大半瞎试的时间。

  • 卡在"正在安装: Ubuntu"且进度条不动:这一步是在下载发行版的 Appx 包。Windows 的安装器给不出细粒度进度,所以你看到的"卡住"很可能是在慢慢下。
  • 报WslRegisterDistribution failed with error: 0x80072ee2:网络超时,包根本没下下来。
  • 报wsl/installdistro/wininet_e_timeout:同样是下载阶段的超时,几乎可以确定是分发服务连不通。
  • 报wsl --update 已禁止(403):这是更新组件拿到的响应被拒绝,跟安装发行版是两码事。

分清楚之后对症下药。0x80072ee2 和 wininet_e_timeout 属于同一类问题——下不下来;403 属于另一类——下是下去了,但被拒。

3.2 分发版清单拉取失败的表现与应对

WSL 在装发行版之前,会先去拉一份"有哪些发行版可以装"的清单。这份清单在微软的内容分发上,如果你的网络对这类跨域请求处理得不好,这一步就会静默失败,然后你在wsl --list --online里看到的是空列表或者报错。

可以先跑一句验证:

wsl --list --online

正常情况下会打印一列发行版名称和友好名。如果这里就报错或者空,说明问题在清单拉取阶段,跟你后面装哪个发行版无关。

处理顺序我是这么走的:

  1. 换一个网络环境(比如从公司网切到手机热点),排除出口设备的干扰。这一步能解决的问题占比最高。
  2. 清一次 DNS 缓存:ipconfig /flushdns,然后重试。
  3. 检查系统时间。时间偏差超过几分钟会导致 TLS 握手失败,表现却像是网络问题。w32tm /resync同步一下。
  4. 尝试走另一条下载路径:
wsl --update --web-download wsl --install -d Ubuntu --web-download

--web-download会绕开应用商店那条链路,直接从微软的 Web 渠道取包。我遇到过好几次商店链路抽风、加了--web-download立刻就好了的情况。

3.3 离线分发包导入:最稳的一条路

如果上面几条都试过还是不行,别耗了,走离线。

思路很简单:把发行版的 rootfs 包下下来,用wsl --import直接导进去,全程不依赖 WSL 自己的下载器。

微软会发布各个发行版的独立分发包,Ubuntu 官方也会在自己的发布页放 WSL 专用的镜像。你要拿到的是一个.tar.gz或者能从.Appx/.AppxBundle里解出来的install.tar.gz。拿到之后:

# 建一个目录放这个发行版的虚拟磁盘 mkdir D:\wsl\Ubuntu # 导入,注意 --version 2 wsl --import Ubuntu D:\wsl\Ubuntu D:\downloads\ubuntu-rootfs.tar.gz --version 2

导入完你会看到一个不太对劲的地方——wsl -d Ubuntu进去之后,提示符是#不是$,用户是 root。这是正常的,--import不会帮你建用户,也不会配置默认用户。

手动配一下:

# 先以 root 进去 wsl -d Ubuntu -u root # 建个和你 Windows 账号同名的用户(名字随你) adduser yourname usermod -aG sudo yourname # 写 /etc/wsl.conf 指定默认用户 cat > /etc/wsl.conf <<'EOF' [user] default=yourname [interop] enabled=true appendWindowsPath=true EOF

然后在 Windows 侧彻底关掉再进:

wsl --shutdown wsl -d Ubuntu

这次的提示符就正常了。这一步的[interop]块很关键,appendWindowsPath=true让你在 WSL 里能直接敲code、explorer.exe这些 Windows 命令;enabled=true是允许互相调用。默认是开的,但--import出来的系统如果 wsl.conf 是空的,有时候行为不太一样,手动写上更踏实。

注意:wsl --import出来的发行版,在wsl --list --verbose里的名字就是你 import 时指定的名字,跟微软商店里的"Ubuntu"是两个独立条目,可以共存。共存的时候注意别搞混,wsl -d 名字要写全。

3.4 wsl --update 报错的几种形态

wsl --update报错一般有这几种:

  • 已禁止(403):请求被拒绝。多数是链路中间有东西在拦,或者本地缓存了错误的响应。先试wsl --update --web-download,不行就去微软的官方文档页找 WSL2 内核更新包(一个.msi),手动下载安装。
  • 无法解析服务器名称:DNS 问题,别在 WSL 里折腾,这是 Windows 侧的解析问题,检查网络适配器的 DNS 设置。
  • 更新完之后wsl --version显示还是老版本:说明更新装到了另一个位置。商店版 WSL 和 inbox 版 WSL 会打架,用wsl --version看版本号,再检查"应用和功能"里是不是装了两个 WSL 条目。

如果是 Docker Desktop 报 "your version of windows subsystem for linux (wsl) is too old",这句的意思很明确——Docker 需要较新的 WSL 内核。它通常还会附带一句 "run the command: wsl --update"。老老实实去更新就行,更新完wsl --shutdown再启动 Docker。

4. 把 Ubuntu 挪到 D 盘:改安装路径的三种做法与代价

4.1 为什么默认装在 C 盘是个隐患

默认情况下,通过商店或者wsl --install装的发行版,虚拟磁盘(ext4.vhdx)放在%LOCALAPPDATA%\Packages\下面,也就是 C 盘。这个文件会随着你装依赖、下代码不断长大。一个重度使用的 Ubuntu,50G 到 100G 都很常见。

C 盘被吃掉一半之后,Windows 更新会失败、临时文件写不进去、各种奇怪的报错开始冒出来。所以装之前就把路径规划好,比装完了再迁要省事得多。

4.2 export/import 迁移法完整命令

这是兼容性最好的方法,任何版本的 WSL 都能用。核心是导出一个 tar、注销原发行版、再导入到新位置。

# 1. 先关掉所有 WSL 实例,避免导出时文件在变 wsl --shutdown # 2. 导出成一个 tar 文件,路径自己定,注意留够空间 wsl --export Ubuntu D:\wsl-backup\ubuntu.tar # 3. 确认导出文件的大小合理(通常几个 G),这一步很重要 dir D:\wsl-backup\ubuntu.tar # 4. 注销原来的发行版(这一步会删掉 C 盘上的 vhdx) wsl --unregister Ubuntu # 5. 导入到新位置 mkdir D:\wsl\Ubuntu wsl --import Ubuntu D:\wsl\Ubuntu D:\wsl-backup\ubuntu.tar --version 2 # 6. 恢复默认用户,否则进去是 root ubuntu.exe config --default-user yourname

第 6 步是新手最容易漏的。--import不会保留原来在/etc/wsl.conf里配的默认用户信息吗?会的,wsl.conf 在 tar 里面,所以其实[user] default=那一行如果之前配过,是会被保留的。但如果你从来没配过 wsl.conf、只是靠ubuntu.exe config --default-user设的,那这个设置在 import 之后就丢了。

稳妥做法是:迁移前先确认/etc/wsl.conf里写了[user] default=你的用户名,这样迁移完就不用额外操心。如果没写,进去补上:

wsl -d Ubuntu -u root echo -e "[user]\ndefault=yourname" > /etc/wsl.conf

然后wsl --shutdown重进。

ubuntu.exe config --default-user这个命令在不同发行版上名字不一样:Ubuntu 是ubuntu.exe,Ubuntu-22.04 可能是ubuntu2204.exe,Debian 是debian.exe。用--import自定义名字导进来的发行版,就没有对应的 exe 了,只能靠 wsl.conf。

4.3 --location 参数与新版本的差异

较新的 WSL(2.0 以后)支持直接在安装时指定位置:

wsl --install -d Ubuntu --location D:\wsl\Ubuntu

这条路干净、省事,不用先装再迁。但有两个前提:你的 WSL 版本够新,以及该发行版支持这个参数。我试过几次,在 Windows 11 + 较新 WSL 上很顺;在老一点的环境里会直接报"未知参数"。

所以我的建议是:先跑wsl --version看版本。如果输出里有 WSL 版本号(不只是内核版本),说明是新版的,可以试--location;如果只输出内核版本,那就是老的 inbox 版,老老实实走 export/import。

4.4 迁移之后容易冒出来的几个问题

迁移不是终点,后面常见的坑有这么几个:

权限问题。从 tar 恢复出来的文件权限一般是对的,但如果你迁移后把项目从/mnt/d/...拷进/home,权限可能会变成 777。用chmod和chown修一下。

磁盘空间没释放。wsl --unregister之后,C 盘上的ext4.vhdx会被删掉,但如果你之前手动调过虚拟磁盘大小,可能会留下一个孤立的.vhdx。去%LOCALAPPDATA%\Packages\下面翻一翻,看到体积异常大的孤儿文件可以删。

名字冲突。如果你没有--unregister就直接--import成同名,会失败。要么换个名字,要么先注销。

启动变慢。放在机械硬盘上的 WSL 虚拟磁盘启动会明显变慢,载入内核和文件系统索引的 IO 都是随机读写。如果 D 盘是机械盘而 C 盘是固态,迁移前掂量一下——空间换性能,值不值看你自己。

5. .wslconfig 与内存配置:别让 Vmmem 吃掉你的内存

5.1 Vmmem 占用高的真实原因

打开任务管理器,你经常会看到一个叫Vmmem的进程占着好几个 G 的内存不撒手,明明 WSL 里什么都没干。这玩意儿就是 WSL2 的虚拟机进程。

原因在于 Linux 的内存管理策略。Linux 会尽可能把空闲内存用作文件缓存(page cache),提升 IO 性能。这些缓存在 Linux 看来是"随时可以回收"的,但虚拟机管理程序不知道,它只看到客户机用了这么多,就向 Windows 报这么多。于是Vmmem的数字就居高不下。

WSL 2.0 之后引入了自动内存回收机制,情况好多了,但仍然不是实时的。最直接的手动办法:

wsl --shutdown

关掉之后 Vmmem 会消失,下次启动重新分配。但这会中断你所有正在跑的东西,不适合频繁使用。真正该做的是给它设个上限。

5.2 .wslconfig 参数逐条说明

这个文件放在 Windows 用户目录下:C:\Users\你的用户名\.wslconfig。注意它管的是所有 WSL2 发行版的全局配置,跟发行版内部的/etc/wsl.conf不是一回事。

一个我常用的配置:

[wsl2] # 内存上限,按机器总内存的 50% 左右给 memory=8GB # CPU 核心数上限 processors=4 # 交换分区大小 swap=4GB # 交换文件位置,默认在 C 盘,建议挪走 swapFile=D:\\wsl\\swap.vhdx # Windows 访问 WSL 服务的端口转发 localhostForwarding=true # 网络模式,mirrored 需要 Windows 11 22H2+ 和较新 WSL networkingMode=mirrored # DNS 隧道,配合 mirrored 用能解决不少域名解析问题 dnsTunneling=true

逐条说下我的取值逻辑:

memory不要给太大。给到机器总内存的 60% 以上,Windows 自己会开始换页,整体反而更卡。16G 的机器给 8G,32G 的给 12-16G,是比较舒服的区间。

processors同理,别把核心数拉满,留一两个核心给 Windows。四个物理核心的机器给 2-3,八核的给 4-6。

swap按 memory 的一半给。太大了没用,太小了编译大项目会 OOM。

swapFile一定要挪,默认在 C 盘。写成D:\\wsl\\swap.vhdx注意是双反斜杠,这是该配置文件里的转义要求,单反斜杠会被当成转义字符处理,路径就错了。这个细节文档里不太显眼,我踩过一次。

networkingMode=mirrored是个好东西,它让 WSL 的网络和 Windows 处于同一个地址空间,localhost 转发、IPv6、DNS 的行为都更符合直觉。但它有版本要求,且某些企业网络环境下会引入新问题,不确定的时候先不开。

5.3 DNS 解析慢、域名不通的处理

WSL 里最常见的网络症状是:ping 8.8.8.8通,但ping baidu.com不通。这说明网络层没问题,是 DNS 解析出了问题。

WSL 默认会在/etc/resolv.conf里自动生成一个指向虚拟网关的 nameserver。这个自动生成的文件经常在切换网络(比如从公司网切到家里)之后就失效了。手工办法两种:

一是在/etc/wsl.conf里关掉自动生成:

[network] generateResolvConf=false

然后手动写/etc/resolv.conf:

nameserver 223.5.5.5 nameserver 119.29.29.29

二是配上dnsTunneling=true,让 DNS 请求走 Windows 侧的解析通道。这条路更省事,尤其是当你 Windows 侧本来就配置了公司内网的 DNS 时,隧道模式能直接复用。

改完/etc/wsl.conf要wsl --shutdown才生效,改.wslconfig也一样。这一点特别容易被忽略——很多人改完配置文件发现没效果,就是忘了这一步。

5.4 配置生效与验证

改完.wslconfig之后的标准流程:

wsl --shutdown wsl -d Ubuntu

进去验证几件事:

# 看内存 free -h # 看 CPU 核心数 nproc # 看 swap swapon --show # 看 DNS cat /etc/resolv.conf

free -h里的 total 应该接近你设的 memory 值(内核本身会占一点点)。如果还是显示宿主机全部的物理内存,说明配置没生效,检查文件路径、文件名(.wslconfig前面有个点,别写成wslconfig)、以及是不是在 Windows 用户目录下而不是 WSL 里。

提示:.wslconfig在 Windows 侧写,/etc/wsl.conf在 WSL 侧写,两者名字相似但职责完全不同。前者管全局资源,后者管单个发行版的用户、挂载、网络行为。搞混了是新手最常见的坑之一。

6. 和宿主工具链打通:VSCode、Docker、CUDA、MATLAB

6.1 VSCode 里用 WSL 的正确打开方式

VSCode 是目前和 WSL 配合得最顺的编辑器,但用法有讲究。

第一步,在 Windows 侧的 VSCode 里装扩展Remote - WSL(现在合并进了 WSL 扩展里)。装完之后,在 WSL 终端里进到项目目录,敲:

code .

VSCode 会以一个"远程窗口"的形式打开,左下角显示WSL: Ubuntu。这时候编辑器的进程一部分在 Windows、一部分在 Linux,扩展也分两边装。

关键经验:扩展必须在 WSL 侧再装一遍。VSCode 会在扩展栏提示 "Install in WSL",尤其是 Python、Pylance、C/C++ 这类需要调用解释器或编译器的扩展,装在 Windows 侧完全没法用。我见过有人抱怨"Python 找不到",就是扩展装错地方了。

另一个常见问题:有人图方便,直接在 Windows 侧用\\wsl$\Ubuntu\home\me\project这样的 UNC 路径打开项目。能用,但不建议。文件监视(file watcher)在这种路径下经常出毛病,热重载失灵,而且性能很差。老老实实从 WSL 终端里code .。

如果想从命令行按路径打开:

code --remote wsl+Ubuntu /home/me/project

这个写法在写脚本、做自动化的时候有用。

6.2 Docker Desktop 与 WSL 后端的报错处理

Docker Desktop 在 Windows 上默认就用 WSL2 作为后端。它会在 WSL 里创建两个特殊发行版:docker-desktop和docker-desktop-data(新版合并成了一个)。wsl --list --verbose里能看到它们。

常见的 "there was a problem with wsl" 报错,八成是这三种情况:

WSL 版本太老。前面说过,wsl --update加--web-download兜底。

这两个特殊发行版状态坏了。表现是 Docker 启动不了、wsl --list里它们显示 Stopped 或者干脆消失。修法:

wsl --shutdown wsl --unregister docker-desktop wsl --unregister docker-desktop-data

然后重启 Docker Desktop,它会自己重建。注意这会丢掉所有镜像和容器数据,因为数据就存在这两个发行版的虚拟磁盘里。有重要数据的话提前docker save备份。

虚拟化没开或者被别的软件占了。BIOS 里的虚拟化(VT-x / AMD-V)没开,或者装了什么游戏反作弊、其他虚拟机软件抢了虚拟化资源。这种情况的报错通常在 Docker 的详细日志里能看到,不在 WSL 的报错里。

还有一个特别容易被忽视的:Docker Desktop 的 WSL 集成是按发行版开关的。设置里那个 "WSL Integration" 列表,你得手动把Ubuntu勾上,不然你在 Ubuntu 里敲docker会发现命令不存在。

6.3 在 WSL 里跑 CUDA 的驱动边界

这是个大坑,很多人在这里绕很久。

规则只有一条:驱动装在 Windows 侧,CUDA Toolkit 装在 WSL 里。

具体说:

  1. 在 Windows 上安装 NVIDIA 显卡驱动。一定要是较新版本的驱动,因为 WSL 的 CUDA 支持是通过驱动里的一个特殊组件(libcuda.so的 Windows 版本,叫nvcuda.dll那套)暴露给 WSL 的。老驱动没有这个能力。
  2. 在 WSL 里不要再装一遍显卡驱动。装了就冲突,nvidia-smi反而会报错。
  3. 在 WSL 里装 CUDA Toolkit:
sudo apt update sudo apt install -y nvidia-cuda-toolkit

或者按官方文档走 apt 源安装特定版本。

验证:

nvidia-smi

在 WSL 里能打印出显卡信息、驱动版本、显存占用,就说明通路是好的。如果提示command not found,是 toolkit 没装;如果提示Failed to initialize NVML,那是 Windows 侧的驱动问题,回去更新驱动。

再验证一下运行时:

nvcc --version

注意nvidia-smi显示的 CUDA Version 是驱动支持的最高版本,nvcc --version显示的是你实际装的 toolkit 版本,两者不一样很正常,只要 toolkit 版本不高于驱动支持的版本就行。

装 PyTorch 的时候,要选 cu 版本,不要选 cpu 版本,否则它根本不用显卡:

pip install torch --index-url https://download.pytorch.org/whl/cu121

版本号要和你的驱动匹配,装之前先看nvidia-smi里的 CUDA Version。

6.4 MATLAB 为什么识别不到 WSL 里的解释器

这个问题挺典型。MATLAB 的pyenv机制只认 Windows 本地的 Python 安装,它没法直接指向一个跑在虚拟机里的解释器。所以你在 WSL 里装好了 Python 和一堆包,MATLAB 那边pyenv里翻来翻去也找不到。

官方支持的路径其实只有一条:MATLAB 用 Windows 侧的 Python。所以如果你的目的只是"在 MATLAB 里调用 Python 函数",那就在 Windows 装一个 Python,配好pyenv。

如果你确实想用 WSL 里的环境(比如那边的依赖更全、或者有 Linux 特有的库),可行的做法是走脚本级调用:

status = system('wsl -d Ubuntu -u yourname python3 /home/yourname/script.py');

这种方式能跑通,但代价是你和 Python 之间隔了一层命令行,传参、拿返回值、传大数组都很别扭。数据交换基本只能靠文件或者标准输出。

我的建议是:别硬凑。MATLAB 和 WSL 的交集本来就小,如果项目里两边都要用,把边界划清楚——MATLAB 做数值计算和仿真,WSL 做数据处理和模型训练,中间用文件(mat、csv、parquet)交换,比互相调用清爽得多。

7. WSL 里那些工具的实际踩坑:binwalk、Python 环境

7.1 binwalk 装出来为什么是老版本

sudo apt install binwalk能装上,但你跑到一个较新的固件上可能会发现它什么都解不出来。这通常不是你的用法问题,而是 Ubuntu 仓库里的 binwalk 版本偏旧。

binwalk 在向新版本演进的这段时间里,依赖和用法都有变化。老版本对某些新的压缩格式、新的文件系统镜像支持不好。想用新特性,就得自己想办法装新版。

一条路是从源码构建。这需要先补齐编译环境:

sudo apt update sudo apt install -y build-essential git python3 python3-pip

然后把源码拉下来,按它的构建说明走。注意 binwalk 的依赖里有一堆解压工具(sasquatch、jefferson、unsquashfs之类),这些在 Ubuntu 仓库里有些能直接 apt 装,有些得自己编译。装全了,解包认得才多。

另一条路是看清楚你现在这个版本的能力边界。如果你只是做常规的文件格式识别和提取,老版本够用;如果你要处理的是新出的芯片固件、OTA 包,那大概率得自己构建一套。

提示:binwalk 这类安全分析工具在 WSL 里跑完全没问题,因为它只是普通用户态程序。但如果你的脚本里涉及到原材料解包后要挂载文件系统,mount在 WSL 里是受限的,需要在 WSL 里以 root 挂载 loop 设备,而且得确认你的 WSL 内核支持你要挂的文件系统类型。这一点和纯 Linux 主机不一样,踩过就知道。

7.2 conda 环境与 PyCharm 的衔接

PyCharm 从 2022.3 开始正式支持 WSL 解释器。配置路径是:File → Settings → Project → Python Interpreter → Add Interpreter → On WSL,选你的发行版,然后填解释器路径。

坑在这几个地方:

conda 必须装在 WSL 里,不是 Windows 里。这是最容易搞错的。有些人在 Windows 上装了 Anaconda,然后想在 PyCharm 里指向 WSL 的解释器,结果发现那个路径根本不存在。正确的做法是在 WSL 里装 Miniconda:

wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh bash Miniconda3-latest-Linux-x86_64.sh

装完之后,环境解释器的路径形如/home/yourname/miniconda3/envs/myenv/bin/python。

尽量不要用~/anaconda3而用~/miniconda3。Anaconda 完整版在 WSL 里占空间还不小,而且很多包你根本用不上。Miniconda 干净。

环境不要建在/mnt/c下面。我见过有人为了让 Windows 侧的 PyCharm 能看到,把 conda 环境建在 Windows 盘上。结果是每次激活环境都要花十几秒,装包更是慢得离谱。环境建在/home下,让 PyCharm 通过 WSL 通道去访问,才是对的姿势。

如果 PyCharm 里添加 WSL 解释器时列表是空的,检查 PyCharm 版本、以及wsl --list --verbose里有没有正常状态为 Running 的发行版。有时候需要先在 WSL 里手动启动一次。

7.3 在 WSL 里跑模型推理工具的注意事项

现在有不少人把 WSL 当成"Windows 上的 Linux 推理机",在里跑各种本地模型工具。这条路是通的,但有几点必须注意。

显存走 Windows 驱动,这个前面说过。nvidia-smi里能看到 GPU,是前提。

内存要配够。模型权重加载到内存里,如果你的.wslconfig里memory=4GB,那稍微大点的模型直接 OOM。根据模型规模调,7B 量级的模型加上 KV cache 和框架开销,通常要 12G 以上才舒服。

模型文件别放在/mnt/c。加载一个几 G 的模型文件,从 9p 协议读进来的速度会让你怀疑人生。放到/home/yourname/models下面。

注意虚拟磁盘膨胀。下载几个模型之后,ext4.vhdx会迅速涨到几十上百 G。WSL 的虚拟磁盘是"只涨不缩"的,删掉文件之后它也不会自动还给你。想回收空间得手动收缩:

wsl --shutdown # 用 diskpart 收缩,或者用 Optimize-VHD(需要 Hyper-V 模块)

这是个慢性问题,用久了才感觉到,提前规划好磁盘位置能省很多事。

8. 卸载、重装与日常故障速查

8.1 干净卸载的完整顺序

卸载 WSL 不是点一下"卸载"就完事,残留物会占着几十个 G。

# 1. 列出所有发行版 wsl --list --verbose # 2. 逐个注销(数据会全丢,提前备份重要的东西) wsl --unregister Ubuntu wsl --unregister docker-desktop wsl --unregister docker-desktop-data

注销之后,去"启用或关闭 Windows 功能"里取消勾选"适用于 Linux 的 Windows 子系统"和"虚拟机平台",重启。

最后清理残留:

  • C:\Users\你的用户名\.wslconfig(如果你不再用 WSL,可以删)
  • %LOCALAPPDATA%\Packages\下面以发行版名字命名的目录
  • 你自己指定的那些虚拟磁盘目录,比如D:\wsl\

想只重置 Ubuntu 而不是整个卸载,那wsl --unregister Ubuntu加重新--import就够了,Windows 功能不用动。

8.2 root 登录与默认用户管理

几个常用操作:

# 以 root 进某个发行版 wsl -d Ubuntu -u root # 忘了用户密码,进去改 wsl -d Ubuntu -u root passwd yourname

改默认用户,最可靠的方式还是写/etc/wsl.conf:

[user] default=yourname

改完wsl --shutdown重进。比ubuntu.exe config --default-user靠得住,也不依赖具体发行版的 exe 名字。

还有个细节:wsl --import进来的发行版,/etc/wsl.conf可能是空的,所以刚进去是 root。这不是坏了,是设计如此。

8.3 常见问题速查表

现象大概率原因处理方向
wsl --install卡在"正在安装"分发包下载慢或断加--web-download,或走离线 tar 导入
0x80072ee2/wininet_e_timeout分发服务连不通换网络、清 DNS 缓存、同步系统时间、离线导入
wsl --update报 403更新链路被拒--web-download,或手动下载内核更新包
Docker 报 WSL 版本太老WSL 内核过旧wsl --update后wsl --shutdown
Docker 启动失败docker-desktop 发行版损坏注销这两个发行版,重启 Docker 重建
Vmmem 占用高Linux 页缓存不回收.wslconfig设 memory 上限,必要时wsl --shutdown
WSL 里域名解析失败resolv.conf 失效关掉generateResolvConf,手写 nameserver 或开 DNS 隧道
nvidia-smi报 NVML 错误Windows 侧驱动问题更新 Windows 显卡驱动,WSL 里别装驱动
PyCharm 找不到 WSL 解释器conda 装在 Windows 侧,或环境在/mnt/cconda 重装到 WSL 的/home下
项目编译/装包特别慢代码放在/mnt/c挪到/home下重新装依赖
C 盘空间莫名减少vhdx 只涨不缩迁移到 D 盘,或手动收缩虚拟磁盘
wsl -d Ubuntu进去是 rootimport 后没配默认用户写/etc/wsl.conf的[user] default=

8.4 关于长期维护的一点经验

用久了之后,我给自己定了几条规矩,分享出来可能对你有用。

每条 WSL 相关的命令我都记在一个纯文本笔记里,包括当时为什么这么改。因为 WSL 的报错信息高度抽象,同一个报错可能对应三种原因,有个记录能省掉大量重复排查。

.wslconfig的每一次修改都配一句注释说明为什么。过半年回来看,你绝对想不起来当初为什么把 memory 设成 10GB 而不是 8GB。

还有一条:升级 Windows 大版本之前,先wsl --export一份备份。系统更新偶尔会动 WSL 的组件,虽然大多数时候没事,但真出事的时候,一份 tar 能让你十分钟回到原样,而不是重装一整天。

9. 几句实际操作中的体会

WSL 这东西,装的时候觉得麻烦,用顺了之后是真的回不去。我现在的工作流基本是:Windows 侧开着浏览器和聊天工具,WSL 里跑终端、编辑器、容器,两边靠code .和 localhost 端口打通,需要传文件的时候直接走\\wsl$路径。整套下来比在虚拟机里折腾共享文件夹舒服太多。

但我最想说的其实是另一件事:WSL 的绝大多数"疑难杂症",根子都在网络和路径这两件事上。卡下载、403、解析失败,全是网络;装包慢、编译慢、磁盘爆,全是路径。你把这篇文章里"代码放 /home""虚拟磁盘放非系统盘"".wslconfig设资源上限"这三条落实了,剩下的问题基本都能自己排查出来,用不着去搜那些一模一样却互相矛盾的教程。

最后一个我踩过的教训:别同时装商店版 WSL 和手动下载的内核更新包。这两个东西版本不一致的时候,wsl --version给你的信息是混的,你会以为自己更新成功了,实际上运行时用的是另一个。判断方法很简单——wsl --version输出的第一行如果有 WSL 版本号(形如WSL 版本: 2.x.x),说明你用的是新版独立组件;如果只有内核版本,那就是老的 inbox 版。分清楚自己用的是哪个,后面所有的更新和排错才有的放矢。

返回列表