☰
WSL2磁盘扩容全攻略:VHDX虚拟磁盘与文件系统一次搞定
2026/10/6 3:14:34 网站建设 项目流程

先问一句:你的C盘是不是又飘红了?Windows下装WSL这几年,我遇到最多的问题不是“WSL怎么装”,而是“WSL把C盘吃光了怎么办”。每次执行完wsl --shutdown,我看着那个几十GB的ext4.vhdx文件发呆好久:明明Linux里没装几个软件,虚拟磁盘怎么就能长这么大?后来折腾了无数次才知道,WSL扩容和Windows普通分区扩容完全是两码事,里面藏了很多细节。

这篇我把WSL磁盘扩容的完整思路、底层原理、实操命令和踩坑记录全部捋清楚。无论你是虚拟磁盘上限不够想直接放大,还是C盘空间不足想把整个WSL迁到D盘,又或者是扩容后发现df -h没有变化,都能在这篇里找到对应解法。全程按实践顺序写,命令可以直接复制,适合所有不想在这件事上浪费半天时间的WSL用户。

1. 先搞清楚扩容对象:WSL的“硬盘”到底藏在哪

1.1 ext4.vhdx:那个体积惊人的“大文件”

很多人一直以为WSL装在Windows里就是一堆文件夹,直到C盘告警才发现,真正的大户是一个叫ext4.vhdx的文件。这个文件就是WSL的整个虚拟磁盘,WSL2里的Ubuntu、Debian、openSUSE等发行版,所有Linux文件系统数据都封装在这个VHDX文件里。

默认情况下,它藏在这里:

C:\Users\<你的用户名>\AppData\Local\Packages\

具体的发行版包名不同,目录也不一样。比如Ubuntu 24.04通常是:

C:\Users\<你的用户名>\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu24.04LTS_xxxxx\LocalState\ext4.vhdx

我第一次找这个文件的时候,在Packages目录里足足翻了一分钟。最快的方式不是在资源管理器里一层层点,而是直接在PowerShell里执行:

Get-ChildItem -Path "$env:LOCALAPPDATA\Packages" -Filter "ext4.vhdx" -Recurse | Select-Object FullName, @{N='SizeGB';E={[math]::Round($_.Length/1GB,2)}}

这条命令会把所有发行版的VHDX位置和实际大小一次性列出来,很直观。看到那个动辄30GB、50GB的文件,你就明白C盘为什么不够用了。

1.2 为什么没装几个软件,C盘却被吃光

WSL的VHDX默认是动态增长的虚拟磁盘,不是一次性占满空间的。你刚装完发行版时,这个文件可能只有几百MB。但用着用着,它会一点点变大,而且有几个情况会让它疯涨:

  • Docker Desktop挂到WSL里时,镜像、容器、volumes全存在WSL的文件系统里,overlay2目录能轻松吃掉十几GB。
  • 开发依赖比较重的项目,node_modules、Python虚拟环境、CUDA和PyTorch等包一装就是好几个GB。
  • 编译缓存、日志、apt缓存这些“看不见的垃圾”在WSL里越堆越多,而你在Windows的“磁盘清理”里根本看不到它们。

最关键的是,你在WSL里删掉文件后,VHDX文件不会自动缩小。它可以只增不减,除非你手动做compact操作。这就是很多人反复清理Linux内部空间,C盘却一点没变少的根本原因。

搞清楚这一点后,扩容的思路就清晰了:要么把这个VHDX文件本身的上限调大,要么把它整个挪到别的盘,顺便给C盘减负。

2. 扩容前必须搞懂的三件事

2.1 VHDX是动态增长的虚拟磁盘

先理解VHDX是个什么东西,用生活类比很简单:它就像一个能自动变大的行李箱。你往里面装衣服,箱子会跟着撑大;你把衣服拿出来,箱子却不会自动缩小,需要手动压一压才恢复体积。在箱子里能装多少衣服,取决于箱子的“标称容量”;箱子实际占了家里多少地面,才是C盘上真正占用的空间。

WSL2默认给这个箱子的标称容量通常很大,有些版本是256GB,较新的版本默认上限是1TB。所以日常使用中,大多数人遇到的不是“WSL提示磁盘满”,而是“C盘被VHDX实际占用撑爆了”。当然也有另一种情况,虚拟磁盘上限设置得比较小,Linux里才用了几十GB就提示No space left on device,这就真正需要扩容了。

两种情况的处理路径完全不同。前者优先考虑迁移或者清理,后者优先考虑直接放大VHDX。

2.2 扩容是“两层空间”的事

这是最容易踩坑的地方。WSL扩容要同时做两件事:

第一层,Windows侧:把VHDX文件的上限调大,比如从200GB扩到512GB。这一步让“行李箱标称容量”变大,但行李箱本身还没有变鼓。

第二层,Linux侧:把分区和文件系统扩展到新的容量,也就是在Linux里执行growpart和resize2fs。这一步才是真正让Linux系统“看到”并“用上”新增空间的关键。

只做第一层、不做第二层的后果,就是你在WSL里执行df -h,磁盘大小跟扩容前一模一样。我自己就犯过这个错,expand完VHDX回到WSL发现没变化,还以为命令没生效,后来才意识到还要resize文件系统。

2.3 动磁盘前的备份,最佳姿势是什么

扩容操作本身风险不算高,但任何对虚拟磁盘的操作都有翻车可能,尤其是在Windows更新、磁盘驱动或PowerShell模块出问题时。我的建议是:操作前至少做一次导出备份。

WSL的备份命令很简单:

wsl --shutdown wsl --export Ubuntu D:\backup\ubuntu.tar

注意,导出的tar文件会非常大,和WSL里实际使用空间相当。如果C盘已经没空间了,导出文件一定要放到别的盘,比如D盘。导出耗时取决于数据量,几十GB可能要等十几分钟到半小时,中间别去动终端。

注意:如果磁盘空间真的很紧张,导出前先在Linux里做一次清理。把apt缓存、包管理器缓存、旧的Docker镜像清一遍,删之前先给WSL“瘦身”,再导出备份,压力会小很多。因为导出的是整个文件系统,垃圾越多导出越久越占空间。

另外,新版WSL还支持直接导出为VHDX格式:

wsl --export Ubuntu D:\backup\ubuntu.vhdx --vhd

我个人觉得普通用户用tar格式就够了,通用性更好;VHDX格式更适合后面想直接用import-in-place注册的场景,一会细说。

3. 实操扩容:两条能落地的路线

3.1 路线一:diskpart直接放大VHDX

适用情况:C盘本身空间还够,只是WSL内部的虚拟磁盘上限不够,或者是想给df -h里已经满掉的空间续命。操作速度最快,不用等导出导入。

第一步,完全关闭WSL。注意不是关闭窗口,而是把所有发行版都停掉:

wsl --shutdown

然后确认所有发行版都变成Stopped状态:

wsl -l -v

看到State一列全是Stopped之后再继续。如果还有Running,可能是后台进程占用,先关掉相关程序,再执行一次wsl --shutdown。

第二步,用diskpart扩展VHDX。在PowerShell里执行:

diskpart

进入diskpart交互环境后,依次输入:

select vdisk file="C:\Users\<你的用户名>\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu24.04LTS_xxxxx\LocalState\ext4.vhdx" expand vdisk maximum=524288 detach vdisk exit

这里maximum=524288的单位是MB,也就是512GB。如果原来是256GB想扩到512GB,就是512 * 1024 = 524288。想扩到1TB就写1048576。数字按需算,别把单位搞错,不少人在这里把MB和GB搞混,导致容量翻倍或减半。

expand vdisk之前不需要attach。如果系统提示虚拟磁盘正被占用,说明WSL没完全停掉。diskpart执行成功会显示“DiskPart successfully expanded the VHDX file”。如果用的是家庭版Windows,没有Hyper-V模块,Resize-VHD这个PowerShell命令可能用不了,diskpart反而是最通用的方案。

第三步,也是很多教程漏掉的一步:回到WSL里扩展文件系统。这一步放到第4节专门讲。

3.2 路线二:导出导入,顺手把WSL搬到D盘

适用情况:C盘已经飘红,没有空间给VHDX“长大”,或者你想把整套Linux环境从C盘搬到D盘长期使用。这种方式相当于“重新部署”一个WSL发行版,效果是换了家,顺便把容量也重置了。

流程分四步:

第一步,备份当前环境:

wsl --shutdown wsl --export Ubuntu D:\backup\ubuntu.tar

第二步,注销当前发行版。这里要特别注意,注销会移除当前注册的WSL实例,但不会删除你导出的tar文件:

wsl --unregister Ubuntu

执行完这一步,原来C盘里的ext4.vhdx会被删除,C盘空间立刻释放。这也是很多人说的“卸载WSL”最干净的方式。

第三步,重新导入到目标目录:

wsl --import Ubuntu D:\WSL\Ubuntu D:\backup\ubuntu.tar --version 2

这里D:\WSL\Ubuntu是新的安装位置,可以自己指定。导入需要几分钟,完成后D:\WSL\Ubuntu\ext4.vhdx就是新的虚拟磁盘了。

注意:wsl --import导入的发行版默认用户会变成root,而且默认不会把之前的默认用户恢复。这个坑在第5节里详细讲怎么修。

第四步,进入WSL,扩展文件系统(同样是第4节的内容),因为导入的镜像文件系统大小通常还是原来的分区大小。

如果之前导出用的是VHDX格式,新版WSL还支持直接注册:

wsl --import-in-place Ubuntu D:\backup\ubuntu.vhdx

这种方式不需要解包tar,注册速度很快,但前提是你导出的就是VHDX文件。我叫它“极简迁移方案”,适合已经把WSL环境折腾到极度满意、不想动任何文件系统配置的读者。

3.3 两条路线怎么选

直接说结论,我做了一个对比表,方便你对号入座:

场景推荐路线原因
C盘空间充足,但WSL内部磁盘上限不够diskpart扩VHDX快,不用重新导入,风险最低
C盘空间不足,需要给C盘腾位置导出导入到D盘一次性解决C盘压力,顺便备份
想换个更大的固态盘继续用WSL导出导入迁移和扩容一步到位
只是虚拟磁盘上限不够,C盘还有几十GB剩余diskpart扩VHDX省时间,不需要重新配置默认用户
电脑是新装的,WSL里没啥重要数据直接wsl --unregister后重装比扩容更快更干净

选路线时最重要的判断依据其实是C盘剩余空间。C盘都红了,就别想着diskpart扩容了,因为扩展VHDX文件本身不会释放任何空间,只是修改一个数字。先把WSL迁走,才是真正给C盘续命。

4. 文件系统扩容:让WSL真正用上新增空间

4.1 用lsblk和df确认当前的“感量”

不管走哪条路线,扩容操作中都有一天避不开:进入WSL执行文件系统扩展。先别急着敲命令,先看清楚当前系统里磁盘的情况。

进入WSL后,执行:

df -h lsblk

df -h看的是文件系统使用情况,lsblk看的是块设备和分区结构。WSL2里,VHDX虚拟磁盘一般显示为/dev/sdb,分区是/dev/sdb1,挂载在/下。如果你看到的是/dev/sda也别慌,不同环境和驱动版本下盘符会有差异,以lsblk为准。

重点看两列:SIZE和AVAILABLE。如果VHDX已经expand过了,但df -h显示根分区还是原来的大小,说明分区和文件系统还没扩展到新空间。这时候就需要growpart和resize2fs上场。

4.2 growpart + resize2fs完整操作

以典型的/dev/sdb1为例,完整操作流程如下:

第一步,检查文件系统完整性,有错误先修复:

sudo e2fsck -f /dev/sdb1

如果文件系统没问题,这一步会快速跳过。如果有错误,它会提示你是否修复,选yes即可。这一步不是可选项,直接resize一个不健康的文件系统,有丢数据风险。

第二步,扩展分区:

sudo growpart /dev/sdb 1

这里的意思是:把/dev/sdb磁盘的第1个分区扩展到磁盘末尾。如果系统提示growpart: command not found,需要先安装工具:

# Ubuntu/Debian sudo apt update && sudo apt install cloud-guest-utils -y # CentOS/RHEL sudo yum install cloud-utils-growpart -y

第三步,扩展文件系统:

sudo resize2fs /dev/sdb1

这条命令会把ext4文件系统扩展到整个分区。执行完再次运行:

df -h

你会发现根分区大小已经变成expand时设置的目标容量了。整个过程从执行到结束通常不到一分钟,比在Windows上扩展分区快多了。

这里有个细节:我的VHDX上限改了,但Linux系统里文件系统是ext4还是xfs,决定了最后一步命令不同。ext4用resize2fs,xfs用xfs_growfs /。默认Ubuntu是ext4,AlmaLinux、CentOS等很多RHEL系默认xfs。

4.3 CentOS/其他发行版特供命令

既然热搜词里频繁出现“centos7 根目录扩容”,这里单独把CentOS系的操作写一下。CentOS默认用的文件系统很可能是xfs,所以流程是:

sudo yum install cloud-utils-growpart -y sudo growpart /dev/sdb 1 sudo xfs_growfs /

xfs_growfs /表示把根文件系统扩展到最大可用大小。执行成功后同样用df -h确认。

Debian系和Ubuntu类似,用resize2fs就行。如果是openSUSE之类的发行版,先看文件系统类型,df -T /确认,再选对应的grow命令。

如果你在扩容时发现分区是LVM逻辑卷,比如CentOS分区结构里有/dev/mapper/cl-root这种路径,那还需要多两步:先pvresize扩展物理卷,再lvresize扩展逻辑卷,最后再扩展文件系统。WSL2默认环境很少用LVM,但如果你手动配置过,或者导入了完整的CentOS镜像,就需要先确认一下。

5. 扩容路上踩过的坑,和我最后的救场

5.1 没停WSL就操作,虚拟磁盘被占用

这个坑我踩得特别透彻。最早一次我跑到Windows Terminal里敲diskpart,输入select vdisk后系统提示“虚拟磁盘服务错误:虚拟磁盘正在使用中”。当时我一脸茫然,明明终端窗口都关了。

后来才明白,关掉WSL终端窗口并不等于停止WSL发行版。很多服务进程、后台任务还在跑,VHDX一直被系统锁定。正确的姿势是先执行wsl --shutdown,再用wsl -l -v确认所有发行版State为Stopped。甚至有时候你以为停了,但Windows里的某些程序还挂着WSL会话,比如Docker Desktop,那就要把Docker Desktop整个退掉再试。

如果确认没有WSL进程还是报占用,可以重启一次Windows再操作,别硬刚。我试过硬刚很多次,结果都是失败告终。

5.2 导出导入后默认用户变成root

使用wsl --import重新导入发行版的人,十个里有八个会遇到这个情况:登录进去发现用户名是root,之前的用户名和密码全都不好使了。

原因是--import导入的发行版不会保留旧的默认用户配置。解决办法很简单,在WSL里创建或修改/etc/wsl.conf:

[user] default=你的用户名

改完执行wsl --shutdown重启WSL生效。如果导入后发现系统里根本没有原来的用户目录了,先用root登录,手动创建用户再设置默认用户:

useradd -m -s /bin/bash 你的用户名 chown -R 你的用户名:你的用户名 /home/你的用户名

顺便把sudo权限也加上,不然很多命令跑不了。

另外还有一种更快的临时解法,用发行版对应的exe设置默认用户,比如Ubuntu:

ubuntu.exe config --default-user 你的用户名

但推荐优先用wsl.conf,因为新版本WSL对这套方式支持更标准。

5.3 删了文件,C盘空间不返还

这是很多人测出“扩容后C盘也没变大”的迷惑性原因之一。你在WSL里删了文件,VHDX文件大小不会自动缩回去。那怎么把“瘦身”后的空间还给C盘?

方法一,diskpart手动压缩。先停止WSL,然后:

wsl --shutdown diskpart select vdisk file="C:\...\ext4.vhdx" attach vdisk readonly compact vdisk detach vdisk exit

compact会把VHDX里未使用的空间清零并压缩,文件就变小了。注意:compact要求磁盘必须只读挂载,所以一定要加readonly,别乱写。压缩后C盘可能多出来几个GB甚至十几GB,效果很明显。

方法二,用新版WSL的“稀疏VHD”功能。如果你的WSL版本支持,可以执行:

wsl --manage Ubuntu --set-sparse true

开启后VHDX会自动回收未使用的空间,不用每次手动compact。但要注意,Hyper-V等虚拟机软件对稀疏VHD的兼容性不如普通VHDX稳,这个功能看个人取舍。

5.4 常见问题与排查速查表

问题原因解决办法
diskpart expand报“磁盘正在使用”WSL还在Running或Docker占用wsl --shutdown后确认所有发行版Stopped,退出Docker Desktop
expand成功但WSL里df -h没变化没有扩展Linux分区/文件系统执行growpart /dev/sdb 1+resize2fs /dev/sdb1
growpart: command not found系统没有安装cloud-guest-utilsUbuntu安装cloud-guest-utils,CentOS安装cloud-utils-growpart
导入后默认用户是root导入不保留旧的默认用户配置配置/etc/wsl.conf的[user]字段,重启WSL
xfs文件系统用resize2fs报错文件系统类型不是ext4用df -T /确认类型,xfs改用xfs_growfs /
VHDX越来越大,C盘空间被吃光动态磁盘不自动回收用diskpart的compact vdisk手动压缩,或开启sparse
导入的发行版systemd起不来新版WSL默认没有开启systemd在/etc/wsl.conf里设置[boot] systemd=true
扩容后发现WSL进不去分区表或文件系统扩展出错先e2fsck -f修复,再重新growpart,不要重复执行多余命令

这些坑我基本都踩过一遍,尤其在文件系统类型搞混这个问题上,曾经把一台xfs的WSL当ext4处理,执行resize2fs直接报错,吓出一身冷汗。其实只要先查类型再动手,整个过程是很稳的。

最后聊点实际体会。我个人现在的习惯是:首次装好WSL后,直接把VHDX上限设置成自己短期内够用的值,比如512GB,然后定期在Linux里清理apt缓存和Docker废弃镜像,再用compact vdisk把空间还给C盘。这样一来,C盘空间吃紧的概率大大降低。如果哪天新项目需要大量数据,需要迁移,就直接导出导入到数据盘,根本不用纠结C盘。

扩容这个事,本质上就是“Windows层扩大容器,Linux层扩大文件系统,最后检查空间”,顺序别乱,命令别漏。希望这篇能让你的WSL不再成为C盘杀手。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询