上周我在win11上折腾了一件事:给WSL里的Ubuntu 24.04再装一个副本,并且把两个实例重命名成自己能一眼看懂的名字。起因很简单,主力环境已经养得很肥——编译链、CUDA、Python虚拟环境、VSCode Remote-WSL的整套配置全在里面。我想装ROS2 humble、跑binwalk的固件分析、试一下Linux版微信,又不想把这些可能互相打架的依赖塞进主力环境。WSL实例之间是互相隔离的完整rootfs,比conda/venv那种"同一系统下的虚拟环境"隔离得更干净,所以我决定直接开第二个实例。
本以为自己很懂WSL,动手才发现"安装两个"这三个字里全是坑。最大的坑在于,WSL的实例名(DistributionName)是唯一标识,直接再次执行wsl --install -d Ubuntu-24.04,得到的不是第二个Ubuntu,而是"已安装"的提示。想要两个独立实例,必须绕开同名注册的限制。而绕开限制之后,又带来一个新问题:两个实例名字差不多怎么办?于是"安装两个"和"重命名"这两件事,在我实际折腾里彻底绑到了一起。
下面这些内容就是我的完整实操记录,包含命令、原理和踩坑过程。如果你也有类似需求——想在WSL里同时维护开发环境和实验环境,或者只是想把wsl -l -v里那一堆默认名理顺——可以参考我这套思路。
1. 为什么需要同时运行两个Ubuntu 24.04:主力环境与实验环境的隔离需求
1.1 主力环境的"养肥"困境
用过WSL一段时间的人都会有个共同感受:环境越用越值钱。以我为例,当前这个Ubuntu 24.04实例是年初从WSL 2.0开始用的,里面装了完整的GCC/Clang编译链和CMake构建体系,CUDA Toolkit和cuDNN也配好了,日常写代码用的Python 3.12环境里顺手装了torch和numpy,再加上git、docker、以及一堆调了好久的VSCode Remote-WSL插件配置。这些东西一旦被搞坏,重新搭一遍的成本没法估。
实验性质的东西恰恰最喜欢"污染"环境。比如热搜里常见的"ubuntu24.04安装ros2humble",ROS 2的依赖树非常大,安装过程中会把一堆Python包、消息库、可视化工具拷进系统;再比如"wsl使用binwalk",binwalk是固件分析工具,经常要装各种二进制分析依赖,有时还配合pip install一堆奇怪的包。这些都该和主力开发环境隔离开,不然某天apt upgrade时一个依赖冲突就能让你一整天都耗在修环境上。
WSL在这方面的优势是天然的:每个实例都有独立的rootfs、独立的用户空间、独立的系统配置。你在实验实例里装坏了什么,删掉重来就是,完全不碰主力环境。这比conda、venv那种"同一系统下隔离"的方案要彻底得多,因为连内核模块、systemd服务、/etc配置这些底层东西都是分开的。
1.2 "名字一样"造成的实际困惑
装第二个实例之前,我先用wsl -l -v确认了一下现有实例的完整信息,输出长这样:
NAME STATE VERSION * Ubuntu-24.04 Stopped 2看起来只有一个,对吧?问题就出在装第二个实例时。WSL不允许出现两个完全同名的发行版,当你尝试再装一个Ubuntu-24.04时,它会提示名称已存在。我用export/import绕开限制后,给新实例起了个临时名字,可很多人的做法是找网上的脚本、镜像包强行绕过,最终得到"Ubuntu-24.04"和"Ubuntu-24.04_1"这种混乱命名。这种状态下用wsl -d切换,你根本分不清哪个是主力、哪个是实验区。
重命名的需求就是这么冒出来的。后来我把两个实例统一成了Ubuntu2404-Main和Ubuntu2404-Lab,一个负责日常开发,一个专门跑实验和测试,一眼就能看出来该进哪个环境,再也不用拿终端记录去猜了。
2. 动手前的关键检查:WSL版本、系统组件与在线安装的坑
2.1 先确认WSL版本再谈操作
虽然win11里一般不会出现WSL 1.x这种古董版本,但WSL 2.0之后的功能差异很大。比如后面要用的wsl --export --vhd参数,就是较新版本才支持的;WSL 2.0.9以后的autoMemoryReclaim也是新版本特性。所以正式开始前,我建议先看一眼版本:
wsl --version输出类似这样:
WSL 版本: 2.3.26.0 内核版本: 5.15.167.4 WSLg 版本: 1.0.51只要WSL版本号是2.x,本文的方法基本都能用。如果版本过老,可以先wsl --update升级。这里多说一句,"wsl --update下载很慢"是搜索词里高频出现的问题,我也遇到过。它卡在"正在下载适用于 Linux 的 Windows 子系统"的进度条好几分钟不动,多半是网络环境的问题,换个时段重试、或者关闭占用带宽的下载任务,往往就好了。如果你急着用,其实完全可以跳过wsl --install的在线安装步骤,直接用后面要讲的rootfs导入方式,照样能得到完整的Ubuntu 24.04实例,而且基本不受这次下载慢的影响。
2.2 系统组件和虚拟化检查
WSL 2依赖两个Windows功能:虚拟机平台(VirtualMachinePlatform)和适用于Linux的Windows子系统。正常情况下装过WSL的人这两项都是开启的,但如果你想在一台没装过WSL的机器上从头搭,或者排查启动失败,可以这样确认:
dism.exe /online /get-featureinfo /featurename:Microsoft-Windows-Subsystem-Linux dism.exe /online /get-featureinfo /featurename:VirtualMachinePlatform需要管理员权限的CMD或PowerShell。更直观的方式是打开"启用或关闭Windows功能",把这两个选项勾上重启。另外,虚拟化必须在BIOS/UEFI里打开,在任务管理器的"性能 -> CPU"页面能看到"虚拟化:已启用"的字样。这一步常被忽略,尤其是老机器从win10升级到win11之后,有一小部分主板默认没开启虚拟化,WSL 2就会一直报错或者切回WSL 1。
2.3 备份等于给自己买保险
接下来的操作不管是导出导入还是改注册表,都建议先给现有实例做一次快照。WSL没有自带快照功能,但导出其实就是快照:
wsl --shutdown wsl --export Ubuntu-24.04 D:\WSLBackup\ubuntu2404-before-change.tarWSL 2.0以上版本还可以用--vhd参数直接导出为vhdx:
wsl --export Ubuntu-24.04 D:\WSLBackup\ubuntu2404-before-change.vhdx --vhd这里有个细节:wsl --export前必须先wsl --shutdown,否则会提示实例正在使用或者导出不完整。导出时间取决于你的rootfs大小,我那个装了一堆工具的实例大概导出了10多分钟。备份这一步千万别跳,我后来在改注册表之前就吃了"以为自己稳,结果差点把DistributionName改错"的亏,还好有备份能退回去。
3. 获取第二个Ubuntu 24.04实例:导出导入法与rootfs导入法实测
3.1 为什么直接执行wsl --install -d不行
先说最常见的误区。很多人拿到"装第二个Ubuntu"这个需求,第一反应就是敲:
wsl --install -d Ubuntu-24.04如果你第一次装Ubuntu 24.04用的就是这条命令,那现在再执行一次大概率会得到两种结果:一是走Microsoft Store渠道的时候提示"该应用已安装",二是命令行渠道检测到同名发行版直接拒绝创建。这不是bug,是设计如此——DistributionName在WSL里是唯一标识。同一个名字不能注册两次。
所以"安装两个"的正确思路,是给第二个实例起一个新名字,绕开同名限制。这也是为什么本文的重心会落在"导出导入"和"重命名"上——因为在WSL的使用哲学里,实例名从创建那一刻起就应该表达用途。
3.2 方法一:从现有实例导出再导入(复制主力环境)
如果你希望第二个实例里已经带着一部分配置,比如apt源、常用工具、开发环境底子,就用这条路。我的完整操作是这样:
wsl --shutdown wsl --export Ubuntu-24.04 D:\WSLBackup\ubuntu2404-template.tar wsl --import Ubuntu2404-Lab D:\WSL\Ubuntu2404-Lab D:\WSLBackup\ubuntu2404-template.tar --version 2逐条解释一下参数:
- Ubuntu2404-Lab:新实例的名字,可以任意起,建议用字母、数字、连字符,别用中文和空格。
- D:\WSL\Ubuntu2404-Lab:新实例的根目录,ext4.vhdx虚拟磁盘会放到这里。目标目录不要跟旧实例混在一起,方便以后单独压缩和迁移。
- D:\WSLBackup\ubuntu2404-template.tar:刚才导出的tar归档文件。
- --version 2:强制指定WSL 2模式。
执行完wsl --import后,跑一下:
wsl -l -v此时你已经有了两个Ubuntu 24.04实例:原来的Ubuntu-24.04和新的Ubuntu2404-Lab。文件、用户、系统配置都被复制过来了。
如果你担心tar导出/导入会丢掉一些WSL 2的新特性,可以用--vhd方式:
wsl --export Ubuntu-24.04 D:\WSLBackup\ubuntu2404-template.vhdx --vhd wsl --import Ubuntu2404-Lab D:\WSL\Ubuntu2404-Lab D:\WSLBackup\ubuntu2404-template.vhdx --vhd --version 2--vhd的好处是导出后的文件就是原始虚拟磁盘,导入更快,虚拟磁盘的稀疏属性保持得更接近原生;缺点是体积大。tar方式更适合归档和跨机器迁移。两种方式导入后的实例,在文件系统层面没本质区别,主要看你手头场景更适合哪种。
3.3 方法二:从rootfs直接导入(全新环境)
如果你想要的是一个干净的Ubuntu 24.04,不想背着主力环境的历史包袱,可以从Ubuntu官方渠道拿rootfs tar.gz,比如ubuntu-24.04-minimal-cloudimg-amd64-rootfs.tar.gz这类文件,然后:
wsl --import Ubuntu2404-Dev D:\WSL\Ubuntu2404-Dev D:\Downloads\ubuntu-24.04-minimal-cloudimg-amd64-rootfs.tar.gz --version 2rootfs导入同样能指定任何你喜欢的实例名。而且它不依赖在线商店,速度受网络影响小得多——如果你正好卡在"wsl --install太慢"或"wsl --update下载很慢"上,这招可以绕过那些坑。
从cloud image rootfs导入的实例默认用户是root,没有走Ubuntu首次启动的OOBE流程。进去之后需要自己建普通用户、配sudo、装基础工具。这反而适合完全自定义的场景。我自己最常用的是方法一,因为每次在新实例里重新配置.zshrc、VSCode插件、git config都很烦;如果只是给客户做演示、跑一次性实验,方法二更符合"用完即弃"的定位。
4. 给WSL实例重命名:两种方案与它们的适用边界
4.1 路线一:export/import强制改名
在上一节的操作里,我们其实已经通过"导入时指定新名字"实现了新实例的命名。如果你需要一个旧实例彻底改头换面,思路也差不多:先导出,再以新名字导入,最后删除旧实例。命令示例:
wsl --shutdown wsl --export Ubuntu-24.04 D:\WSLBackup\rename-tmp.tar wsl --import Ubuntu2404-Main D:\WSL\Ubuntu2404-Main D:\WSLBackup\rename-tmp.tar --version 2 wsl --unregister Ubuntu-24.04这套流程的优点是:改的是注册信息,底层文件系统整体搬过去了,系统里的用户、文件、服务都还在。缺点是:导入后默认用户变成root,需要重新配置默认登录用户;迁移期间磁盘占用会膨胀,tar导出是对整个rootfs的归档;如果实例里配了systemd服务、自启动任务,导入后可能需要重新启动一遍。
wsl --unregister这个命令要谨慎用,它会删除实例的根目录和所有文件。执行前务必确认新实例已经正常启动过,里面的文件都完整了。
4.2 路线二:直接改注册表DistributionName
如果不想重建虚拟磁盘,只想把显示的实例名改掉,注册表是更快的路径。操作分四步:
第一步,彻底停止WSL:
wsl --shutdown第二步,打开注册表编辑器,进入:
计算机\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss第三步,这里会有若干个以GUID命名的子键,每个子键代表一个WSL发行版。关键字段如下:
| 字段 | 含义 | 说明 |
|---|---|---|
| DistributionName | 实例在wsl -l -v里显示的名字 | 要改的就是它 |
| BasePath | 虚拟磁盘所在路径 | 用于确认哪个GUID对应哪个实例 |
| DefaultUid | 默认用户的UID(0表示root) | 建议顺手检查 |
| Version | 2表示WSL2 | 不要随意改 |
通过BasePath可以定位到具体实例。比如BasePath指向某个目录包含LocalState和ext4.vhdx,基本就能确认它是哪一个Ubuntu。确认无误后,双击DistributionName,把值改成你想要的新名字(例如Ubuntu2404-Main),确定保存。
第四步,回到终端验证:
wsl -l -v名字已经变了,直接wsl -d Ubuntu2404-Main能正常进入。
注意,修改注册表前一定要先wsl --shutdown。如果LxssManager还在运行,新的DistributionName不会被加载,甚至可能出现状态不一致的情况。修改前建议右键Lxss键选择"导出",留一份备份,改错了还能还原。
4.3 两种方案怎么选
| 方案 | 路径操作 | 默认用户 | 适用场景 | 风险 |
|---|---|---|---|---|
| export/import改名 | 重建实例 | root | 彻底搬家、顺便清理老配置 | 耗时较长,需重新配置用户 |
| 注册表改名 | 原地改名 | 保持原状 | 只改显示名、快速落地 | 操作前需做好备份 |
我的做法是混合使用:主力实例Ubuntu2404-Main保留原始文件系统,只用注册表改名;实验实例Ubuntu2404-Lab用export/import创建,因为它本来就该是"可丢弃"的,随时可以重新导入。你在实际使用中也可以按这个思路来,主环境尽量少动底层结构,实验环境大胆造。
5. 改名后的连锁反应:Terminal、VSCode与默认用户的完整排查
5.1 Windows Terminal里的旧配置残留
WSL实例改名或者新增之后,Windows Terminal会自动为它生成一个新的profile,但旧profile不会自动消失。打开Windows Terminal设置,你会发现左边多了一个新发行版入口,同时旧名字的入口还挂在列表里。点击旧名字最终会启动失败,因为wsl.exe -d 旧名字已经找不到目标了。
我的处理步骤:
- 打开Windows Terminal设置(Ctrl+,);
- 在"配置文件"里找到旧名字生成的profile,手动删除;
- 新建配置文件,命令行填wsl.exe -d Ubuntu2404-Main,启动目录填\wsl$\Ubuntu2404-Main\root;
- 给这个profile起一个容易记的名字,比如"U2404-Main"。
如果你习惯直接改settings.json,也可以在里面找到对应distribution字段的profile删掉。WSL动态生成的profile一般会有source标记,清理时不要误删手动配置过的profile。
5.2 默认用户从普通用户变成root的问题
这是重命名/导入后最容易踩的坑。原本Ubuntu 24.04首次启动时OOBE会创建一个普通用户(比如dev),带sudo权限。但通过wsl --import导入的实例不执行OOBE,启动后默认登录root,whoami输出root。原因就是导入过程中没有携带默认用户信息,也没有写入/etc/wsl.conf的user段。
解决方式有两个:
- 临时指定用户:wsl -d Ubuntu2404-Lab -u dev,这样以dev身份进入;
- 永久设置默认用户:编辑目标实例里的/etc/wsl.conf
[user] default=dev然后wsl --shutdown,再启动实例,默认用户就变成dev了。注意dev必须已经存在于/etc/passwd里,如果rootfs里没有可用用户,先手动创建:
useradd -m -s /bin/bash dev passwd dev usermod -aG sudo dev这一步做完,基本就还原了正常Ubuntu的使用体验。如果是注册表改名路线,默认用户会沿用原来的DefaultUid,通常不会遇到这个问题。
5.3 VSCode Remote-WSL连接失败的排查链路
改名对VSCode的Remote-WSL影响比较隐蔽。如果你之前在VSCode里打开了\wsl$\Ubuntu-24.04\home\dev\myproject这样的路径,改名后旧的WSL目标就失效了,Remote Explorer下拉列表还显示旧名字,点击连接大概率会卡在"正在启动VS Code Server"或者直接报错。
完整排查链路如下:
- 先确认WSL实例本身是否健康:在Windows终端执行wsl -d 新名字,能进入且whoami是预期用户,说明实例没问题;
- 再看wsl -l -v里的名字和版本是否正常;
- 如果Remote Explorer里没有新名字,关掉VSCode重开,让它重新扫描WSL发行版;
- 如果扫描到了但连接卡住,多半是VS Code Server组件需要重装:在WSL终端里执行code .,VSCode会自动下载server组件到~/.vscode-server,等它装完再连;
- 如果资源管理器里的\wsl$路径仍指向旧名字,重启一次系统或重启Windows Explorer。
我实际操作中遇到的是第4种情况,重新执行code .之后,VSCode右下角弹出重新加载窗口,选Reload Window马上就好了。这里有个经验值得分享:WSL实例名在VSCode里是作为连接标识的,名字变了等于"换了台机器",旧会话的信任状态、扩展同步都要重新触发一遍。改名前把VSCode里打开的WSL文件夹记录导出一份,能省不少事。
6. 多实例的日常管理:资源分配、空间回收与使用习惯
6.1 .wslconfig全局资源配置
一台win11机器上跑多个WSL实例,资源分配问题迟早会碰到。WSL 2的架构是所有实例共享同一个轻量级虚拟机,内存和CPU都在C:\Users\你的用户名.wslconfig里统一配置:
[wsl2] memory=8GB processors=6 swap=4GB autoMemoryReclaim=gradualautoMemoryReclaim是WSL 2.0.9以上版本放出的参数,取值有gradual、dropcache、disabled。它能在实例空闲时自动把宿主机内存收回来,解决"WSL吃满内存不吐"的老毛病。如果你经常同时开着Main和Lab两个实例,建议加上这一行。
要注意.wslconfig是全局配置,修改后需要wsl --shutdown再重启WSL会话才生效。目前还不能给单个实例单独分配CPU或内存,这是WSL设计理念决定的——实例之间共享资源池,而不是每个实例独占一台VM。
6.2 删除文件后vhdx空间不释放的压缩方案
"wsl linux删除文件后空间没释放"是很多人都会搜的问题。原因很简单:ext4.vhdx是动态扩展的虚拟磁盘,你在Linux里rm掉几十GB文件,宿主机看到的还是那个胖胖的vhdx文件,不会自动瘦身。压缩方法:
第一步,彻底停止WSL:
wsl --shutdown第二步,用管理员身份打开CMD,进入diskpart:
diskpart select vdisk file="C:\Users\你的用户名\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu24.04LTS_xxxxxx\LocalState\ext4.vhdx" attach vdisk readonly compact vdisk detach vdisk exit路径要替换成你自己的实际路径。用wsl --import放到自定义目录的实例,直接去那个目录找ext4.vhdx即可。
如果装了Hyper-V模块,也可以用PowerShell:
Optimize-VHD -Path "D:\WSL\Ubuntu2404-Lab\ext4.vhdx" -Mode FullOptimize-VHD的Full模式比diskpart更彻底,但耗时也更长。为避免频繁压缩,比较好的习惯是定期清理:
sudo apt clean sudo journalctl --vacuum-time=3d清完再压缩,文件能小不少。我在实验实例上常用这套组合,压缩后vhdx能减掉几个GB。
6.3 多实例环境下我养成的几个小习惯
技术细节聊完了,随手分享几个日常习惯。我现在把WSL实例名当成"环境标签"来用,命名规则统一是Ubuntu2404-用途,比如Ubuntu2404-Main、Ubuntu2404-Lab、Ubuntu2404-Build。每天启动实例尽量用显式命令wsl -d Ubuntu2404-Main,而不是直接敲wsl——后者一定进入默认实例,默认实例经常切换,还是显式指定靠谱。
给多个实例设置默认入口也有个小技巧:
wslconfig /s Ubuntu2404-Main这样打开wsl.exe会直接进入Main实例。临时想切到Lab,就wsl -d Ubuntu2404-Lab,不用改默认配置。
还有一点经验是:WSL实例变了名字之后,Docker在WSL里的配置、systemd服务、自启动脚本都会受到影响,需要回到实例内部确认systemctl status是否正常。有一回我给实验实例配了daemon.json,改名后docker一直起不来,检查才发现忘了在wsl.conf里开systemd:
[boot] systemd=true加上这一行再wsl --shutdown重启,一切如常。这篇文章里提到的所有命令,我自己都用了一遍,踩过的坑也都标注出来了。如果你也卡在"有两个实例却分不清谁是谁"的尴尬里,照这个思路把名字理顺、把默认用户配置好,日常切换会舒服很多。