1. 装之前先搞清楚:今天的 WSL 和你印象里的不是一回事
WSL、Ubuntu、Linux、Windows 这四个词放在一起,很多人第一反应还是"虚拟机那套东西"。我差不多每隔半年就会帮同事装一次 WSL,最大的感受是:真正让人踩坑的从来不是安装命令本身,而是脑子里那套过时的认知。有人还在手动开"适用于 Linux 的 Windows 子系统"功能、手动下载内核更新包、手动去商店点安装——这套流程在 2021 年是对的,但放到 2025 年已经属于绕远路。
现在的 WSL 是一个完整的、微软持续迭代的产品线,一条wsl --install就能把功能开关、内核、发行版、WSLg 图形支持全部拉起来。它解决的问题很具体:让习惯 Windows 桌面生态的人,在不放弃原生 Windows 的前提下,拿到一个几乎无损的 Linux 开发环境。适合的人群也很明确——写后端、写脚本、搞数据、做嵌入式交叉编译、需要跑一堆 Linux 工具链的人;以及单纯想学 Linux 常用命令、但又不想折腾双系统的新手。
我先说一个容易忽略的事实:WSL 的体验差异,90% 来自你选了 WSL1 还是 WSL2,以及你的项目文件放在哪个盘上。这两件事在安装阶段如果没定好,后面会觉得"WSL 怎么又慢又难用",然后跑去装虚拟机,白白绕一大圈。
1.1 WSL1 与 WSL2 的架构分野,以及为什么默认该选 2
WSL1 的本质是一层系统调用翻译层。你敲ls,它把 Linux 的系统调用翻译成 Windows 内核能听懂的调用,没有真实 Linux 内核在跑。好处是文件系统是同一套,/mnt/c和 Linux 目录之间没有隔阂,启动快、内存占用小。坏处也非常直接:需要内核模块的东西跑不了,Docker 跑不起来(准确说是跑不好),ptrace、inotify这类行为有偏差,一些二进制程序直接段错误。
WSL2 换了个思路,它在一个轻量级的虚拟化层里跑真正的 Linux 内核。这意味着兼容性基本和原生 Linux 一致,Docker 能用,systemd 能开,GPU 直通能做。代价是跨系统文件访问要走网络文件协议,所以你在 WSL 里读/mnt/c/Users/...下的文件,性能会比 Linux 原生目录差一个数量级。
选型结论很干脆:除非你有非常特殊的理由(比如必须让 Windows 程序和 Linux 程序编辑同一批文件且不能复制),否则一律选 WSL2。微软现在也把 2 作为默认版本,wsl --install装完之后wsl -l -v看到的 VERSION 列就是 2。
注意:如果你的机器比较老,WSL2 需要 CPU 支持虚拟化(Intel VT-x / AMD-V)并且在 BIOS 里开启。装之前进 BIOS 看一眼,比装到一半报错再回头折腾省事得多。
1.2 三种"在 Windows 上跑 Linux"的路子,各自适合谁
我把常见方案摆在一起对比,你按自己的场景对号入座就行。
| 方案 | 启动速度 | 资源占用 | 与 Windows 文件互通 | 图形界面 | 适合场景 |
|---|---|---|---|---|---|
| WSL2 | 秒级 | 动态,按需分配 | 方便但跨系统访问慢 | 内置 WSLg | 开发、脚本、命令行工具链 |
| 传统虚拟机 | 十几秒到一分钟 | 固定占用,通常 2G 起 | 需要共享文件夹 | 完整桌面 | 需要完整桌面、需要模拟多机 |
| 双系统 | 重启切换 | 独占硬件 | 基本不通 | 完整桌面 | 把 Linux 当主力系统 |
WSL2 的优势区间就是"我 90% 时间在 Windows,但那 10% 需要 Linux 命令行"。虚拟机的优势区间是"我需要一个可以随便折腾、随时快照回滚的完整系统"。这两者不冲突,很多人是 WSL 日常用、虚拟机偶尔开。
有个细节值得说:WSLg 从 2022 年起内置在 WSL 里,意味着你在 Ubuntu 里装个 GUI 程序(比如某个图形化的调试工具),窗口能直接弹在 Windows 桌面上,不需要额外配 X Server。这一点比早年方便太多了,早年要先装 VcXsrv 再配 DISPLAY 环境变量,配错一个字就黑屏。
2. 安装前必须定的三件事:版本、位置、内核
很多人拿到教程直接复制粘贴命令,装完才发现"咦,怎么装的是 22.04 不是 24.04",或者"我的 C 盘怎么少了 15 个 G"。安装前的三分钟规划,能省掉后面两小时的迁移。
2.1 Ubuntu 版本怎么挑:LTS 与非 LTS 的真实差别
Ubuntu 的发布节奏是固定的:偶数年 4 月发一个 LTS(长期支持)版本,支持 5 年;中间每半年发一个非 LTS,支持 9 个月。2025 年 10 月这个时间点,LTS 是24.04 LTS,同时 Ubuntu 25.10 已经发布。
我的建议很明确:开发环境一律选 LTS。原因不是"LTS 更稳定"这种套话,而是具体的三点。第一,第三方软件源和 Docker 镜像基本都优先适配 LTS,非 LTS 上你经常会遇到某个 PPA 没有对应版本的包。第二,公司内部文档、CI 脚本、团队约定通常都以 LTS 为基准,你一个人用非 LTS 会出现"在我这儿能跑"的经典问题。第三,非 LTS 9 个月就要升级一次,升级过程本身是有风险的操作,尤其是你已经在里面装了一堆环境的时候。
想试新特性的情况也有,那就单独装一个非 LTS 发行版实例,和主力 LTS 实例并存。WSL 支持同时装很多个发行版,互不干扰,wsl --list --online能看到完整清单。
需要注意 WSL 里的发行版名称和 Ubuntu 官方版本号不完全对应,早期商店里的 "Ubuntu" 就是最新 LTS,后来微软改成了带版本号的命名,比如Ubuntu-24.04。你可以在wsl --list --online的 NAME 列里看到确切的标识。
2.2 要不要把发行版挪出 C 盘
WSL 发行版的默认安装位置在%LOCALAPPDATA%\Packages\下面,也就是 C 盘的用户目录里。一个干净的 Ubuntu 大概占 1.5 到 2 GB,但你把项目、依赖、Docker 镜像都放进去之后,几十个 G 很正常。
我的习惯是从一开始就装到数据盘。两种做法:
一种是装完之后迁移。wsl --export导出成 tar 包,wsl --unregister注销原实例,再wsl --import导入到目标目录。这个操作会丢一部分元信息,比如固定的 IP 之类(本来也是动态的),但用户数据和配置都在,实测可靠。
另一种是直接下载 rootfs 自己导入,跳过商店安装这一步:
# 在 Windows PowerShell 中执行 mkdir D:\WSL\Ubuntu2404 wsl --import Ubuntu2404 D:\WSL\Ubuntu2404 D:\downloads\ubuntu-24.04-rootfs.tar.gz --version 2注意:
--import导入的实例默认登录用户是 root,这不符合日常使用习惯。装完后需要在/etc/wsl.conf里写默认用户,或者用发行版自带的配置程序指定。具体做法在 3.3 节里展开。
顺便说一个很多人不知道的优化:WSL2 的虚拟磁盘(ext4.vhdx)是动态增长、不会自动收缩的。你在里面删了 30G 文件,Windows 那边看磁盘占用还是那么大。这时候要用wsl --manage <发行版> --resize之类的管理命令,或者先wsl --shutdown再想办法压缩 vhdx。所以定期看一眼占用是必要的习惯。
2.3 一条命令之前的系统检查清单
正式动手前,我会快速过一遍这几项,省得中途卡住:
- 系统版本:
wsl --install这条命令需要 Windows 10 版本 2004(内部版本 19041)及以上,或者任意 Windows 11。在 PowerShell 里敲winver能直接看到版本号。 - 虚拟化是否开启:任务管理器 → 性能 → CPU,右下角看"虚拟化"是不是"已启用"。没启用就进 BIOS 开 VT-x / SVM。
- 磁盘剩余空间:至少留 20 GB,因为 WSL 的虚拟磁盘会随使用增长。
- Windows 更新状态:
wsl --install依赖系统组件,系统补丁太旧会失败。先跑一次更新。 - 终端选择:Windows Terminal 已经是系统自带的了,比老的 cmd 窗口好用太多,支持字体配置、多标签、分屏。后面 4.3 节的字体美化全都基于它。
这一圈检查下来大概三分钟,但能避免"命令敲下去报一堆看不懂的错"这种情况。
3. 安装全过程实录:从 wsl --install 到首屏欢迎语
准备工作做完就可以动手了。我按实际会遇到的顺序写,包括出问题之后怎么排查。
3.1 官方一条命令安装的完整流程拆解
先用管理员身份打开 PowerShell(或 Windows Terminal 的 PowerShell 配置),然后:
wsl --install这条命令实际上做了这么几件事,理解它对排查问题很有帮助:
- 启用"适用于 Linux 的 Windows 子系统"和"虚拟机平台"两个 Windows 可选功能;
- 从微软的更新渠道拉取 WSL 的运行时组件(一个 appx 包);
- 下载并注册默认发行版(现在默认是 Ubuntu 的某个 LTS 版本);
- 把 WSL2 设为默认版本。
第一条执行完之后,通常需要重启电脑才能真正生效。重启后系统会自动继续后面的步骤,弹出一个 Ubuntu 窗口让你创建用户名和密码。
如果你想指定发行版,用-d参数:
wsl --list --online wsl --install -d Ubuntu-24.04wsl --list --online会列出所有可装的发行版,包括 Ubuntu 各版本、Debian、Kali、openSUSE 等。想装多个就多执行几次wsl --install -d <名字>。
装完之后用这几个命令确认状态:
wsl --version # 看 WSL 本身的版本 wsl --status # 看默认发行版、默认版本、内核版本 wsl -l -v # 列出所有实例及运行状态wsl -l -v的输出里有一列 STATE,Running 表示正在运行,Stopped 表示已关闭。WSL2 实例空转一段时间后会自动进入 Stopped,这是正常的省电行为,不是崩了。
3.2 wsl --install 卡住或者慢到离谱时怎么办
这是搜索量最高的问题之一:wsl --install跑了半小时,进度条一动不动。我先解释原因,再给方案。
慢的原因通常有三个层次。第一层是系统功能启用后需要重启,有些教程没提这一点,导致命令卡在某个阶段等重启。第二层是组件下载源的速度问题,WSL 运行时包和发行版镜像要下载几百 MB 到 1 GB 左右,具体速度取决于你所在的网络环境——公司内网有流量管控、或者网络出口拥塞的时候会非常慢。第三层是Microsoft Store 参与安装的情况,商店本身的下载队列有时候会卡住。
对应的处理办法,按优先级排:
方案一,先单独更新 WSL 运行时。分两步走,可以看清楚卡在哪:
wsl --update wsl --install -d Ubuntu-24.04 --web-download--web-download这个参数会让安装走网页下载通道而不是商店通道,实测在很多网络环境下明显更快,也更少出现卡在商店队列的情况。
方案二,手动启用功能再装。如果一条命令整体失败,拆开来做更容易定位:
# 以管理员身份执行 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart # 重启之后 wsl --set-default-version 2 wsl --install -d Ubuntu-24.04方案三,完全离线导入。这是我在网络条件最差的时候用的办法,最可靠。思路是从 Ubuntu 官方下载 WSL 用的 rootfs 镜像(一个 tar.gz 或 tar.xz),然后用前面 2.2 节说的wsl --import导入。这种方式对网络的要求只有"能下到那个文件",下载工具怎么下、下多久都不影响后续流程,也没有商店环节。
离线导入的好处还有一个:可以精确控制装在哪个目录,不会像商店安装那样先落到 C 盘用户目录里再让你迁移。
注意:离线导入的实例不会自动创建普通用户,首次进去是 root。别急着用 root 跑日常开发,配置默认用户的操作见下一节。
3.3 首次进 Ubuntu 该做的四件事
无论是商店安装还是离线导入,进去之后第一件事都是建普通用户、设默认用户,然后跑一次完整更新。
对商店安装的流程,首次启动会自动弹出一个设置界面,让你输入 UNIX 用户名和密码。用户名建议全小写、不带特殊字符,因为很多脚本会把它当成路径片段或者数据库用户名。密码输入时终端不会显示任何字符,包括星号,这是 Linux 的常规行为,不是键盘坏了。
对离线导入的实例,需要手动来:
# 在 Ubuntu 里执行 adduser dev usermod -aG sudo dev然后在 Windows 侧编辑配置。/etc/wsl.conf是 WSL 特有的配置文件,控制挂载、启动、网络等行为:
[boot] systemd=true [user] default=dev [automount] enabled = true options = "metadata,umask=22,fmask=111"改完之后在 PowerShell 里执行wsl --shutdown完全关闭,再重新进入,配置才生效。这里顺带开了 systemd,后面装 Docker、用systemctl管理服务会方便很多,属于"早晚要开,不如现在开"的配置。
第三件事是更新软件包索引并升级:
sudo apt update && sudo apt upgrade -y sudo apt install -y build-essential curl wget git unzip zip vim htop tree这一串是我每台机器都会装的"起步包"。build-essential给了 gcc、make 这些编译工具,很多 Python 包的源码编译依赖它;unzip/zip处理压缩包;tree看目录结构特别直观;htop比自带的top好用。装这些一次到位,比后面遇到一个装一个省事。
第四件事是确认时区,不然日志时间会对不上:
timedatectl set-timezone Asia/Shanghai date4. 让 Ubuntu 好用起来:源、中文、字体三件套
系统装好只是跑起来了,离"好用"还有一段距离。这一步做不做,直接决定你后面是天天抱怨还是天天顺手。
4.1 apt 源替换与 apt update 的正确姿势
默认的 Ubuntu 源在国外,apt update慢是常态。换国内镜像源是最常见的优化手段,但这里有个版本差异的坑必须说清楚。
Ubuntu 24.04 开始,软件源配置文件的格式变了。老版本是/etc/apt/sources.list一行一条的格式,24.04 改成了 deb822 格式,文件在/etc/apt/sources.list.d/ubuntu.sources。你要是照着老教程去改sources.list,会发现那个文件基本是空的或者是注释,改了半天没效果。
24.04 的配置大概长这样:
Types: deb URIs: https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ Suites: noble noble-updates noble-backports Components: main restricted universe multiverse Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg Types: deb URIs: https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ Suites: noble-security Components: main restricted universe multiverse Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg改之前先备份,改完执行sudo apt update。如果报 GPG 错误或者 404,大概率是 Suites 里的代号写错了。代号可以用lsb_release -cs查,24.04 是noble,22.04 是jammy,25.10 是questing。
注意:
apt upgrade和apt full-upgrade不一样。前者只升级现有包,后者允许安装新包、删除冲突包。日常用apt upgrade就够了,full-upgrade偶尔会把你不想动的东西卸掉,尤其是在你手工编译过某个组件的情况下。
4.2 中文显示与输入:终端输入和 GUI 输入是两码事
这是被问得最多、也最容易绕晕的一块。要分清两个场景。
场景一:在 Windows Terminal 里用 WSL 终端。中文输入走的是 Windows 自己的输入法,你按 Shift 切一下就能打中文,Ubuntu 里完全不需要装任何输入法框架。中文显示一般也正常,因为 Windows Terminal 用的是系统字体做回退。这一块其实没什么可折腾的,很多人上来就去 Ubuntu 里装搜狗输入法,装了之后发现终端里还是用 Windows 输入法,白折腾。
场景二:在 WSLg 里跑 GUI 程序。比如你在 Ubuntu 里装了某个图形化编辑器或者浏览器,这时候要输入中文,就必须在 Linux 侧装输入法框架。主流方案是 fcitx5:
sudo apt install -y fcitx5 fcitx5-chinese-addons fcitx5-frontend-gtk3 fcitx5-frontend-qt5然后设置环境变量,通常在~/.profile或/etc/environment里:
export GTK_IM_MODULE=fcitx export QT_IM_MODULE=fcitx export XMODIFIERS=@im=fcitxGUI 输入法这块我个人的实际体验是:能跑通,但多多少少有点别扭,输入法候选框定位、切换响应都可能不跟手。如果你主要是在终端里干活,我的建议是别装,直接用 Windows 输入法,省心。
中文显示还有一个常见问题是中文字体缺失,表现为 GUI 程序里中文变成方框。装一套基础字库就能解决:
sudo apt install -y fonts-noto-cjk fonts-noto-color-emoji fc-cache -fvfonts-noto-cjk覆盖了简繁日韩的常用字形,fc-cache -fv刷新字体缓存。这一步在跑那些会渲染中文的 GUI 工具(比如某些数据可视化面板)时特别必要。
4.3 终端字体选型:怎么调出接近 macOS 的观感
终端好看不好看,字体占七成。macOS 上大家觉得舒服,很大程度上是因为默认那套字体的字重、字距、连字处理得比较克制。想在 Windows Terminal 里复现这种感觉,主要看三件事:等宽、有 Nerd Font 图标补丁、中文与英文能对齐。
先说字体推荐,都是我用过一段时间的:
| 字体 | 特点 | 适合谁 |
|---|---|---|
| MesloLGS NF | Powerlevel10k 主题官方推荐,图标齐全 | 用 zsh + p10k 的人 |
| JetBrains Mono NL | 无连字版本,字符辨识度高 | 不喜欢连字干扰的人 |
| Cascadia Code | 微软出品,Windows 亲和度最高 | 求稳不想折腾的人 |
| Maple Mono NF CN | 自带中文,中英对齐好 | 终端里经常出现中文的人 |
这里有个关键点很多人不知道:中英文混排的终端,如果字体本身没有中文,系统会做字体回退,回退的字体宽度往往不是英文的两倍,结果就是表格、对齐、进度条全乱。所以如果你经常在终端里看中文输出(比如日志里有中文),选一个自带等宽中文的字体能省掉大量对齐烦恼。
Windows Terminal 的配置在设置界面的 JSON 里,改profiles.defaults这一段最省事,对所有 profile 生效:
{ "profiles": { "defaults": { "font": { "face": "Maple Mono NF CN", "size": 11, "lineHeight": 1.1, "weight": "normal" }, "opacity": 95, "useAcrylic": false, "padding": "8, 8, 8, 8" } } }几个参数的作用:lineHeight大于 1 会让行距松一点,视觉上更接近 macOS 那种留白感,但别超过 1.2,否则一屏能看的行数太少;opacity是窗口透明度,95 是轻微的,既有质感又不影响阅读;padding是内边距,给一点会更"透气"。
字体装到 Windows 系统的方法:下载 ttf 文件,全选,右键"为所有用户安装"。装完之后必须重启 Windows Terminal,它才会重新枚举字体列表。这一步漏了会导致你填了字体名但还是显示默认字体,然后开始怀疑人生。
主题配色方面,Windows Terminal 内置了 One Half Dark、Campbell 这些,想更接近 macOS 的暗色观感可以试试 Catppuccin 或者 Tokyo Night 的配色方案,社区有现成的 JSON 直接粘进去。这个纯属审美,不影响功能,按喜好来就行。
5. 把开发链路接到 WSL 上:VS Code、Docker、GPU、Git
环境好看了,接下来是真正干活的部分。这一节的每个点都关系到"能不能跑起来"和"跑起来顺不顺"。
5.1 VS Code 与 WSL 的联调机制,以及 code . 背后发生了什么
在 WSL 里写代码,最顺手的组合是 VS Code + Remote 开发扩展。很多人以为这是"VS Code 打开了 WSL 里的文件",其实机制不太一样,理解它有助于排查问题。
真实流程是这样的:VS Code 本体跑在 Windows 上,当你在 WSL 终端里敲code .时,它启动的是 WSL 里的一个小程序,这个小程序通过一个本地通道告诉 Windows 侧的 VS Code "帮我在这个目录开个窗口"。然后 VS Code 会在 WSL 里启动一个 server 进程,把所有语言服务、终端、调试器都跑在 Linux 侧。你看到的编辑器界面是 Windows 的,但代码补全、构建、运行全在 Linux 里。
这么设计的好处是:扩展装一次就在 Linux 环境里生效,不用考虑跨平台兼容;路径、权限、shell 都是 Linux 的,不会出现"在 Windows 上能编译、在 Linux 上不行"的割裂。
实际操作只要三步:Windows 侧装 VS Code 和 "WSL" 扩展;在 WSL 终端cd到项目目录;敲code .。第一次会在 WSL 里下载 server 组件,大概几十兆,之后就不用了。
扩展是分两套的:Windows 侧一套,WSL 侧一套。你在 WSL 窗口里点"安装扩展",装的是 Linux 侧那份。常见的坑是"我明明装了 Python 扩展,怎么没有补全"——那就是装到 Windows 侧去了。判断方法很简单,看扩展面板里那个扩展有没有显示 "Install in WSL" 的提示。
Server 文件放在~/.vscode-server里。有时候扩展出问题,删掉这个目录重连一次能解决大部分玄学故障。代价是重新下载,所以一般作为最后手段。
5. 2 跨文件系统跑项目为什么会慢十倍
这一条我放在最显眼的位置,因为它是 WSL 使用体验里影响最大的单一因素,而且很多人根本没意识到。
先说结论:项目代码必须放在 Linux 文件系统里,也就是/home/<用户名>/...下面,绝对不要放在/mnt/c/...或者/mnt/d/...。
原因是 WSL2 的架构决定的。Linux 侧的文件系统是虚拟磁盘里的 ext4,原生速度。而/mnt/c这类目录是通过一个网络文件协议(VirtIO-9P 或更新的方案)从 Windows 挂进来的,每次读写都要跨过虚拟化边界做协议转换。单个小文件慢几倍,如果是npm install或者git status这种要遍历成千上万个小文件的操作,慢十倍以上是常态,慢几十倍也见过。
实测对比给你个直观感受,在同一个 SSD 上跑npm install一个中等规模前端项目:
| 项目位置 | 耗时 |
|---|---|
/home/dev/project | 约 25 秒 |
/mnt/c/Users/dev/project | 约 6 分钟 |
差距就是这么夸张。这不是"优化一下会好一点",这是数量级的差别。
所以正确的使用姿势是:Linux 侧用 Linux 的文件,Windows 侧用 Windows 的文件,需要互通的少量文件才通过/mnt/访问。Windows 侧访问 Linux 文件可以走\\wsl$\Ubuntu-24.04\home\dev这个网络路径,在资源管理器地址栏里敲就能进。不过这个路径也是走协议转换的,别拿它做大文件的频繁读写。
顺带一个常见的连带问题:Windows 侧的 Git 尽量不要去操作 WSL 里的目录。Windows 版 Git 处理 Linux 文件时会折腾权限位和换行符,把一个好好的仓库改成满屏 modified。反过来,WSL 里的 Git 也别去git init在/mnt/c的目录里操作。让工具各管各的地盘。
Git 配置上还有两个必设项:
git config --global core.autocrlf input git config --global core.filemode false git config --global user.name "你的名字" git config --global user.email "你的邮箱"autocrlf input表示提交时统一转成 LF、检出时保持原样,这是 Linux 侧最安全的设置。filemode false让 Git 忽略文件权限位的变化,避免因为权限差异产生一堆无意义的改动记录。
5.3 Docker 与 CUDA 在 WSL 里的安装边界
这两个都是"边界感"很强的东西,搞清楚哪些装 Windows 侧、哪些装 Linux 侧,能避免很多返工。
Docker 有两条路。
路线一是 Docker Desktop,它本身就是跑在 WSL2 后端上的,安装后在设置里打开 "WSL Integration",指定哪些发行版能直接用docker命令。优点是图形界面、省心、自动更新;缺点是资源占用大一些,而且是商业产品,公司规模大了要考虑授权问题。
路线二是直接在 WSL 里装原生的 docker-ce。前提是前面/etc/wsl.conf里已经开了 systemd:
# 添加 Docker 官方源(注意用与你发行版代号匹配的仓库) sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo usermod -aG docker $USER最后那条把当前用户加进 docker 组,需要重新登录(wsl --shutdown再进)才生效,否则还是要sudo。这一步漏掉的人特别多,然后觉得自己没装成功。
CUDA 的边界更严格:驱动装 Windows 侧,工具包装 Linux 侧。
具体来说,你在 Windows 上安装的 NVIDIA 驱动本身就带 WSL 支持,WSL 里不需要、也绝对不应该再装 Linux 版的显卡驱动——装了大概率会把整条链路搞坏,症状是nvidia-smi报错或者干脆识别不到设备。
Windows 驱动装好之后,在 WSL 里直接敲:
nvidia-smi如果能看到显卡信息和驱动版本,说明直通已经通了。然后再装 CUDA Toolkit(注意选 WSL-Ubuntu 的对应版本,不要选 Server 版):
wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-keyring_1.1-1_all.deb sudo dpkg -i cuda-keyring_1.1-1_all.deb sudo apt update sudo apt install -y cuda-toolkit-12-6装完在~/.bashrc里加 PATH:
export PATH=/usr/local/cuda/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH最后nvcc -V验证。笔记本双显卡的机器要留意,WSL 里能用的是 NVIDIA 独显,集显不出现在nvidia-smi里是正常的,别以为没装好。
6. 出问题时的排查链条:从 SSH 连不上到解压乱码
前面都是顺利路径,这一节讲不顺利的时候怎么一步步定位。
6.1 SSH 与端口访问不通的三层排查
WSL 里跑个服务,Windows 侧访问不到,这个问题的排查要分三层,从下往上查效率最高。
第一层:服务本身在 WSL 里跑起来了吗。在 WSL 里执行ss -tlnp看监听端口。如果服务只监听了127.0.0.1,那从外部是访问不到的,需要让它监听0.0.0.0。这是最常见的坑之一。
第二层:WSL 里的 sshd 有没有装、有没有启动。Ubuntu 默认不装openssh-server,很多人以为自带了:
sudo apt install -y openssh-server sudo systemctl enable --now ssh sudo systemctl status ssh用 systemd 管理的前提还是前面开的systemd=true。没开 systemd 的话,得手工起/usr/sbin/sshd。
第三层:网络模式决定的访问方式。WSL2 默认是 NAT 模式,WSL 有自己独立的 IP,每次重启都可能变,Windows 侧访问要查当前 IP(ip addr或者hostname -I),很麻烦。从 WSL 2.0 开始有了镜像网络模式,在 Windows 侧的C:\Users\<用户名>\.wslconfig里加:
[wsl2] networkingMode=mirrored dnsTunneling=true autoProxy=false firewall=true镜像模式下,WSL 和 Windows 共享网络接口,localhost直接互通,不用再查 IP,也不用单独配 DNS 和防火墙规则。这个配置我建议默认就开着,能省掉大量网络相关的折腾。改完wsl --shutdown重启生效。
注意:
.wslconfig是 Windows 侧的全局配置,影响所有发行版;/etc/wsl.conf是 Linux 侧的单个发行版配置。两个文件别搞混,位置和格式都不一样。
还有一个容易忽略的点:Windows 防火墙。镜像模式下防火墙策略会跟着变,如果服务起来了、localhost也不通,去看一眼防火墙的入站规则。
6.2 Linux 解压乱码的成因与一次性解决
从 Windows 那边传过来的 zip,解压出来文件名全是乱码,这个问题的根源是文件名编码不一致。Windows 上的压缩工具习惯把文件名按 GBK 编码存进 zip,而 Linux 的unzip默认按 UTF-8 解析,两边对不上就乱码了。
解决办法有三个,按推荐顺序:
方法一,指定编码解压。Ubuntu 的 unzip 支持-O参数:
unzip -O cp936 文件名.zipcp936就是 GBK 的代码页编号。这个方法最直接,前提是 unzip 版本够新。
方法二,用 7z。它对编码的处理更灵活:
sudo apt install -y p7zip-full 7z x -mcp=936 文件名.zip方法三,已经解压乱了再补救。用convmv批量重命名:
sudo apt install -y convmv convmv -f gbk -t utf8 -r --notest 目标目录-r递归,--notest表示真的执行(不加这个参数只预览不修改,建议先预览一遍确认转换结果正确)。
顺带说一个相关的问题:tar 包解压出来的文件权限不对。如果是打包时用 root 打的,解压出来属主可能是某个不存在的 UID,表现为一堆1000:1000这样的数字。用tar --same-owner或者解压后chown -R $USER:$USER修一下就行。
6.3 文件权限、重装与彻底清理
有几个和权限相关的问题值得一提。
第一个是/mnt/c下的文件权限永远是 777,chmod改了也没用,因为文件系统本身不支持 Linux 权限位。前面 3.3 节里/etc/wsl.conf的automount options加了metadata之后,权限位会被记录在 NTFS 的扩展属性里,chmod才能生效。如果某个工具(比如 SSH 密钥检查)抱怨权限太开放,这就是解法。
第二个是 SSH 私钥权限。~/.ssh/id_rsa必须是 600,否则 ssh 会拒绝使用。Linux 文件系统下chmod 600直接生效;如果密钥放在/mnt/c下面,就要靠上面的 metadata 配置。
第三个是重装和彻底清理。WSL 的实例管理其实很干净:
# 备份 wsl --export Ubuntu-24.04 D:\backup\ubuntu-2404-backup.tar # 注销(会删除该实例的所有数据,谨慎) wsl --unregister Ubuntu-24.04 # 从备份恢复 wsl --import Ubuntu-24.04 D:\WSL\Ubuntu2404 D:\backup\ubuntu-2404-backup.tar # 清理未使用的虚拟磁盘 wsl --shutdown我的习惯是在每次做重大改动前先 export 一份。tar 包是完整的,恢复之后环境、配置、数据全在,比重新一步一步装快得多。这个操作花的时间也就是几分钟,性价比极高。
还有一点关于"彻底清理"的:wsl --unregister之后,如果导出目录还在,Windows 那边的磁盘空间不会自动释放,要手动删目录。另外如果之前用--import装到了别的盘,注销后那个盘的 vhdx 文件也要手动删。
我个人折腾 WSL 这些年最深的体会是:它的"坑"几乎都集中在三个决策点上,而不是命令本身。选 WSL2 还是 WSL1、项目放 Linux 侧还是 Windows 侧、配置写.wslconfig还是/etc/wsl.conf——这三个岔路口走对了,后面基本一路顺;走错了,就会觉得"这玩意儿怎么这么难用",然后在各种论坛里翻帖子。
另外分享一个小习惯:我会把装完之后做过的所有配置改动记在一个setup-notes.md里,包括改了哪个文件、加了哪几行、为什么这么改。因为 WSL 实例重装或者换机器是常事,有了这份记录,新机器上照着抄一遍,半小时就能恢复到一个顺手的开发环境。比凭记忆重新踩一遍坑要划算太多。