被 WSL2 的虚拟磁盘塞爆 C 盘这事儿,我猜不少人都经历过。打开资源管理器一看,C:\Users\<用户名>\AppData\Local\Packages\...\LocalState\ext4.vhdx 动辄几十上百 GB,而且你越折腾 Docker、conda、编译项目,它就长得越离谱。更麻烦的是,你在 WSL 里面删了数据,这个 vhdx 文件也不会自动缩回去,空间被白白占着。想要彻底解决,最干净的办法就是把整个 WSL 发行版迁移到非系统盘,同时还应该把 Windows 的虚拟内存页文件(pagefile.sys)一起挪走,双管齐下,C 盘才能真正瘦下来。
本文我会把迁移的完整流程、两条主流迁移路线、迁移后的配置修复,以及常见报错梳理一遍。不管你是手里装着 Ubuntu 24.04、Debian 还是其他发行版,下面这套操作方法都通用。读完你不仅能动手完成迁移,还会理解每个命令背后到底做了什么,以后遇到类似问题也不用发怵。
1. 先弄清楚 C 盘空间到底被什么吃掉了
1.1 不只是“装了个 Linux 子系统”这么简单
很多人对 WSL2 的认知还停留在“Windows 里能跑 Linux 命令”这个层面,觉得它就是一个模拟器或者一个普通应用。但实际上,WSL2 自从采用了轻量级虚拟机架构之后,整个发行版的文件系统是完整存放在一个虚拟磁盘文件里的。这个文件就是 ext4.vhdx,一般是 Windows 自动创建并管理的。
这个 vhdx 文件的特点是动态增长。你刚装完发行版那会儿,它可能只有 1GB 多;你用 apt 装了几百个软件包,它可能涨到 10GB;你再拉几个 Docker 镜像、创建一批 conda 环境,它轻轻松松突破 50GB。最坑的是,你在 WSL 内部执行 rm -rf 删了一堆东西,磁盘空间确实释放了,但 vhdx 文件不会自动收缩——这个文件在 Windows 眼里依然是那 50GB。
1.2 系统盘的容量永远是“看起来够用,用起来紧张”
大多数电脑出厂时,C 盘就那么 256GB 或者 512GB,Windows 系统本身占去一部分,浏览器缓存、微信聊天文件、软件安装包这些再蚕食一大部分。WSL2 的虚拟磁盘如果放任不管,就会进一步挤占系统盘所剩无几的空间。更麻烦的是,C 盘一旦满了,Windows 更新可能失败、软件无法安装、甚至系统出各种莫名其妙的卡顿。所以把 WSL 挪到非系统盘,本质上不是“优化”,而是一种必要的资源管理。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动手之前先摸清底细:迁移前必做的三件事
2.1 检查当前 WSL 版本和发行版状态
迁移前首先要确认你当前装了什么发行版、它们各自处于什么状态。打开 PowerShell 或者 Windows Terminal,执行:
powershell复制wsl -l -v
输出大致长这样:
code复制 NAME STATE VERSION
* Ubuntu-24.04 Running 2
看到 VERSION 是 2 就放心了,绝大多数情况下我们迁移的都是 WSL2 发行版。同时,STATE 如果是 Running,迁移之前必须把它关掉,不然文件被占用,导出会报错。
2.2 留出足够的临时空间
这一步很多人会忽略,导致迁移中途翻车。核心原因是:wsl --export 导出的 tar 包需要空间,wsl --import 导入后的新 vhdx 也需要空间。我建议这样估算:
- 先看一下当前 vhdx 文件占多大(到
C:\Users\<用户名>\AppData\Local\Packages\<发行版包名>\LocalState\ext4.vhdx看属性就行); - 导出的 tar 包大小大概和当前 vhdx 内部实际使用的空间相当,也就是
df -h里看到的 used 值,而不是文件体积; - 由于导入是一个解包重建的过程,目标盘上还需要预留出能够放下解包后完整文件系统的空间。
所以实操上,如果老 vhdx 有 40GB,目标盘至少要有 60GB 以上可用空间才稳妥。宁可多留一些,也别卡在导出到一半时报“磁盘空间不足”。
2.3 想好迁移后的目录结构
很多人习惯把发行版直接放在比如 D:\WSL\Ubuntu-24.04 这样的目录里。我自己的习惯是给每个发行版单独建一个文件夹,并且路径中不要带中文、空格和特殊符号。虽然技术上 WSL 也能处理带空格的路径,但后续你写脚本、配环境变量的时候会遇到各种转义问题,纯英文字符路径最省心。
3. 核心操作:两条迁移路线,我推荐第一条
3.1 路线一:导出导入,最稳妥也最通用
这一步是真正执行迁移的主流程,我把它拆成四步,每一步的命令都要看清再执行。
3.1.1 第一步:关掉所有 WSL 会话
先退出所有已经打开的终端窗口,然后在 PowerShell 里执行:
powershell复制wsl --shutdown
执行完可以再跑一次 wsl -l -v,确保发行版状态是 Stopped。这一步的目的是释放 vhdx 文件锁。如果你开着 WSL 终端、VS Code 远程窗口、Docker Desktop(基于 WSL2),这些都会占用文件,不关掉导出大概率失败。
3.1.2 第二步:把当前发行版导出成 tar 包
在目标盘上先建好目录,比如 D:\WSL\backup,然后执行:
powershell复制wsl --export Ubuntu-24.04 D:\WSL\backup\ubuntu-24.04.tar
这里我解释一下参数:第一个参数是发行版名称,必须和 wsl -l -v 里显示的名字完全一致;第二个参数是导出的目标路径。导出过程中命令行会卡住一段时间,没有任何进度提示,别慌,这是正常的。文件越大耗时越长,40GB 的数据在 NVMe 硬盘上导出可能需要十几分钟到半小时,中间千万别强制关闭窗口。
3.1.3 第三步:注销原来的发行版
确认 tar 包导出完成、且你能看到文件大小和预期相符之后,再执行这一步:
powershell复制wsl --unregister Ubuntu-24.04
这个命令会删掉原发行版在 Windows 上的注册信息和 C 盘里的 vhdx 文件。执行之后你会发现 C 盘空间一下子就腾出来了。这里必须强调:如果你没有完成第二步,或者对导出的 tar 包没有把握,千万不要执行 unregister。这一步不可逆,而且不会像回收站那样给你后悔的机会。
3.1.4 第四步:导入到新位置
powershell复制wsl --import Ubuntu-24.04 D:\WSL\Ubuntu-24.04 D:\WSL\backup\ubuntu-24.04.tar --version 2
三个参数分别对应:发行版名称、目标目录、tar 包路径。--version 2 是指定以 WSL2 模式导入。导入完成后,新的 vhdx 就会出现在 D:\WSL\Ubuntu-24.04\ext4.vhdx。到这一步,迁移的主要工作就算完成了。
3.2 路线二:直接移动 vhdx 文件,适合不想丢失当前会话配置的人
如果你不想执行导出导入那一套,也可以直接“搬家”。原理非常简单:找出发行版的 vhdx 文件所在目录,把整个目录剪切到目标盘,然后在原来的位置创建一个目录链接(junction)指过去。这样 Windows 以为发行版还在原位置,但实际上数据已经躺在别的盘上了。
先找到 vhdx 的真实路径。发行版的注册表信息保存在 HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss 下面,执行:
powershell复制Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss\*" | Select-Object DistributionName, BasePath
看到 BasePath 就是发行版的存放目录,进去之后会发现 LocalState\ext4.vhdx。操作步骤如下:
wsl --shutdown关闭所有 WSL 进程;- 把整个
BasePath对应的文件夹(比如C:\Users\yourname\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu24.04_...)剪切到D:\WSL\Ubuntu-24.04; - 在原来的路径位置打开管理员 CMD,执行:
cmd复制mklink /J "C:\Users\yourname\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu24.04_..." "D:\WSL\Ubuntu-24.04"
这样就建好了一个目录链接,系统访问原路径时会自动指向新盘。
这条路线的优点是不需要重新解包、不需要重设默认用户,原有 Linux 环境里的一切都原封不动。缺点是整个过程要手动操作注册表目录,如果路径搞错或者链接建错,发行版可能直接无法启动。所以除非你的发行版数据特别大(比如 100GB 以上)、导出一次实在太耗时,我一般还是推荐导出导入法。
4. 迁移收尾:重置默认用户、验证系统、清理备份
4.1 导入后默认用户变成 root 的坑
用导出导入法迁移后,你会发现一个很别扭的现象:打开 WSL 终端直接就是 root 用户,原来的普通用户不见了。这不是数据丢了,而是导入操作默认把发行版的默认用户重置为 root。解决方法是重新设置默认用户。
最简单的方式是编辑 wsl.conf 文件。启动 WSL 终端(现在是 root),执行:
bash复制vi /etc/wsl.conf
如果文件不存在就新建一个,写入以下内容:
ini复制[user]
default=你的用户名
保存之后,在 PowerShell 里执行 wsl --shutdown,然后再重新进入 WSL,你会发现默认用户已经恢复正常了。这个配置对 Ubuntu、Debian、Kali 等绝大多数主流发行版都有效。
4.2 验证 WSL 是否真正跑起来了
基本配置改完之后,一定要做一轮功能验证,别急着关窗口。我通常按顺序检查:
- 基础登录:
wsl -d Ubuntu-24.04能否正常进入,用户名是否正确; - 文件系统完整性:
df -h查看根分区挂载情况,确认 vhdx 已经挂载在/; - 网络连通性:
ping -c 4 8.8.8.8或者curl -I https://mirrors.ustc.edu.cn,确认网络正常; - 挂载盘访问:检查一下
/mnt/d/是否能看到你的非系统盘内容,WSL 跨盘访问是否正常; - 重要服务:如果你之前配了 Docker、SSH、数据库等,试着启动一下,确认迁移没有破坏这些服务。
如果上面任一步骤出错,先别慌,大概率可以通过改 wsl.conf 或者重装发行版解决。我都放在后面一节讲。
4.3 确认一切正常后再清理备份
这一步非常关键。很多人迁移成功后,看着 C 盘空间还没释放,就急着去删东西。正确做法是:
- 先让 WSL 正常跑几天,做一些实际开发工作;
- 确认没有用到什么缺失的配置、没有奇怪的报错;
- 确认完毕之后,再去删除
D:\WSL\backup\ubuntu-24.04.tar这个 tar 备份。
tar 包动不动几十 GB,留着也占地方,确认没问题就删,这是最后一步空间回收。
5. 顺手把 pagefile.sys 也迁走,C 盘才能真省心
5.1 为什么 WSL 和 pagefile.sys 会互相“打架”
WSL2 是虚拟机架构,Linux 内核需要内存,你在 WSL 里跑大型编译、开一堆进程、偶尔还加个 Docker,Windows 为了兜底,会在 C 盘维护一个很大的虚拟内存页面文件 pagefile.sys。这个文件平时就不小,WSL 内存占用越高,它就涨得越猛。很多人发现即使把 WSL 迁走了,C 盘空间还是紧张,一查才发现 pagefile.sys 占了二三十个 GB。这就是为什么 WSL 迁移和 pagefile.sys 迁移经常被放在一起讲——它们是一对难兄难弟。
5.2 Windows 11 下迁移 pagefile.sys 的操作步骤
打开“系统属性”面板,最快的方式是按 Win + R,输入 sysdm.cpl 回车,然后切到“高级”选项卡,点击“性能”区域的“设置”,再切到“高级”选项卡,最后点击“虚拟内存”区域的“更改”。这一层层点进去比较绕,你也可以直接在 Windows 搜索框输入“高级系统设置”直达。
进入虚拟内存设置页面后,按这个顺序操作:
- 取消勾选“自动管理所有驱动器的分页文件大小”;
- 在驱动器列表里选中 C 盘,选择“无分页文件”,然后点击“设置”按钮;
- 再选中你的非系统盘(比如 D 盘),选择“系统管理的大小”(或者自定义一个大小),点击“设置”按钮;
- 一路点击“确定”,系统会提示你重启电脑,确认重启。
重启之后,打开资源管理器看 C 盘根目录,pagefile.sys 应该已经消失或者变得非常小,而你会在 D 盘看到这个文件。C 盘空间又腾出来一大块。
5.3 实际操作里的注意事项
第一,不要在重启前强行删除旧的 pagefile.sys,那是系统正在使用的文件,当时可能删不掉,或者删了容易出问题。第二,Windows 在 C 盘保留一个小分页文件其实有助于蓝屏时生成 dump 文件,所以如果条件允许,可以给 C 盘留一个 1024MB 左右的小分页文件,而不是完全设为“无分页文件”。第三,如果你的内存是 16GB 或更大,日常使用中 D 盘的分页文件大概率用不上,设为“系统管理的大小”就行,别手动设一个过大的固定值,反而浪费空间。
6. 迁移路上我踩过的坑:常见问题排查实录
6.1 执行 wsl --export 时报错“系统找不到指定的文件”
这个报错在旧版 WSL 上很常见。多数原因是 WSL 内核服务组件没有正确注册,或者你安装的是比较老的 WSL 1 版本。我的建议是直接把 WSL 组件升级到最新版,管理员 PowerShell 执行:
powershell复制wsl --update
如果更新都报错 403(这个我见过不少次),多半是内部仓库网络传输不稳定,换个网络环境或者稍后再试,一般都能解决。
6.2 导入后执行 wsl -d Ubuntu-24.04 一直卡在“Installing, this may take a few minutes”
导入完成后第一次启动,WSL 需要初始化用户环境、注册服务,卡一阵子是正常的。但如果超过 10 分钟还没动静,可以先开另一个终端执行 wsl --shutdown,再重新进入。还不行的话,检查一下 D 盘目标目录的权限,确保当前 Windows 用户具有完全控制权限。
6.3 默认用户改了 wsl.conf 还是 root
这种情况多半是 wsl.conf 文件格式有问题。注意 [user] 前面的方括号必须顶格,default= 等号两边不要有多余空格。修改完之后,一定要在 PowerShell 里执行 wsl --shutdown 再重新启动,单纯退出终端再进有时候不会触发配置重新读取。
6.4 迁移到新盘后,极端情况下 WSL 启动黑屏或者直接报错
如果发行版还是启动不了,最后的兜底方案也简单:删掉现有配置,重新导入一次。因为 tar 包还在,重新导入的代价不算大。具体操作是 wsl --unregister Ubuntu-24.04,然后重新执行一次 wsl --import 命令,多个英文名、多写一遍路径而已。我自己就有过一次因为 wsl.conf 里写了一个错误配置项导致系统起不来,最后重新导入解决的经历。
6.5 Docker Desktop 迁移后连不上 WSL
如果你用了 Docker Desktop 的 WSL2 后端,迁移发行版路径后可能会遇到 Docker Desktop 找不到后端发行版的问题。处理方式是在 Docker Desktop 的 Settings → Resources → WSL Integration 里,重新关联一下你的发行版,然后重启 Docker Desktop。如果不行,直接重启电脑,大多能恢复正常。
7. 迁移完成之后想再补充几句
WSL 迁移到非系统盘这件事,技术上不复杂,但坑都藏在细节里。我自己第一次迁移时,就是因为没留够临时空间,导出到一半报错;后来学聪明了,每次都会预留两倍的空间,并且导出完成后先确认文件大小差不多,再去 unregister。这套流程走了几次之后,我反而觉得换盘是最顺手的一次。
另外,如果你的工作流里大量依赖 Docker、conda 或者 VS Code 远程开发,迁移完之后多花几分钟检查那些环境变量和路径配置,比直接开工要省心得多。毕竟虚拟磁盘搬了家,某些硬编码的绝对路径可能还是冲着 C 盘去的,这种东西排查起来最磨人。
最后再分享一个小技巧:迁移完之后,你可以定期执行一次 wsl --manage Ubuntu-24.04 --resize 来收缩 vhdx 文件,或者干脆在 WSL 内部先清理 apt 缓存、临时文件,再关闭系统。这样 vhdx 不会越用越臃肿,你的 C 盘和 D 盘都能维持一个比较清爽的状态。
