ARTICLE DETAIL

资讯详情

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

WSL磁盘空间告急?快速扩容VHDX与迁移D盘实战指南

WSL磁盘空间告急?快速扩容VHDX与迁移D盘实战指南 WSL 的磁盘又满了别急着重装。这个问题我前前后后处理了不下二十次最惨的一次是在 Ubuntu 里跑深度学习预处理根目录直接 100%连apt upgrade都报 no space left最后只花了十来分钟把虚拟磁盘从 64G 扩到 160G所有数据原封不动。今天就把 WSL 扩容这套流程完整写一遍为什么满、怎么判断该不该扩、diskpart 怎么操作、以及不想动 C 盘时怎么迁移到 D 盘。文章里的命令都是我在 Win10/Win11 配 Ubuntu 22.04/24.04 上验证过的你照着做基本不会翻车。1. 先搞清楚WSL的磁盘机制为什么动不动就满1.1 动态VHDX的双层空间逻辑WSL2 本质上是一台轻量虚拟机根文件系统放在一个ext4.vhdx虚拟磁盘里。很多人一看到df -h里显示几百 G 已用就以为宿主 C 盘要爆了其实这里藏着两套空间虚拟磁盘的逻辑容量和宿主机上的实际文件大小。ext4.vhdx默认是“动态扩展”的也就是说它有一个逻辑上限但实际只占用你真正写入的数据量。比如虚拟磁盘逻辑上限是 256G里面装了 40G 东西C 盘上这个 vhdx 文件可能只有 40G 出头不会直接占满 256G。你在 WSL 里跑df -h /看到的是虚拟磁盘内部的容量而 C 盘剩余空间是另一回事。所以扩容前第一步不是急着敲命令而是先分清你到底属于哪种情况是 WSL 内部逻辑空间不够了还是宿主 C 盘物理空间不够了。前者用 diskpart 扩 VHDX 就能解决后者光是扩容没用需要迁移或者清理。这个判断做错了后面折腾一小时也是白搭。1.2 到底是什么把空间吃掉了WSL 系统本身其实占不了多少几个 G 顶天了。真正把磁盘撑爆的通常是开发过程中的累积物Docker 镜像和容器层、conda 环境、pip 和 apt 缓存、模型权重文件、日志文件。我遇到过一个特别典型的案例一个跑深度学习项目的 WSL 里光.cache下的模型文件就占了 40 多 G再加上几个 conda 环境直接干到 80G。排查占用不想一个个翻目录的话直接在 WSL 里跑一条命令du -x -h --max-depth1 / 2/dev/null | sort -h从根目录往下看哪个目录体积大一眼就清楚。常见的大头基本是/home、/var/lib/docker、/opt、/usr/local/miniconda3这类路径。清理的时候可以用上sudo apt clean、pip cache purge、conda clean --all、sudo journalctl --vacuum-size100M能回收不少空间。但这里有个坑你在虚拟机里删了文件df -h看着空出来了宿主 C 盘上的 vhdx 文件大小却不一定会缩回去。因为虚拟磁盘不会自动把释放的块还给 Windows。这也是有些人明明清了几十 GC 盘却一点没变的原因。后面我会专门讲怎么把空间真正吐出来。2. 扩容前必做定位VHDX、备份和方案选择2.1 先确认你用的是WSL2而不是WSL1网上很多教程一上来就让你找ext4.vhdx但如果你还在用 WSL1压根没有这个东西。WSL1 的文件直接存在 Windows 文件系统里扩容思路完全不一样。所以第一步先确认版本wsl -l -v输出里会有一列 VERSION如果显示的是 1你需要先转换成 WSL2wsl --set-version 发行版名 2转换时间取决于现有数据量几 G 和几十 G 差别很大耐心等。转换完成后再继续后面的扩容操作。要是转换过程中报错通常和磁盘剩余空间、Windows 功能组件有关先把 WSL2 所需的内核组件和虚拟机平台装好再重试。2.2 用PowerShell找到ext4.vhdx的准确路径确认是 WSL2 之后下一步是找到发行版对应的虚拟磁盘文件。默认路径一般在C:\Users\你的用户名\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu...\LocalState\ext4.vhdx但不同的发行版、不同的安装来源包名和路径都可能不一样。手动一层层翻很容易找错。用 PowerShell 搜最快Get-AppxPackage | Where-Object { $_.Name -like *Ubuntu* } | Select-Object PackageFamilyName拿到 PackageFamilyName 之后再拼出完整路径检查文件是否存在$pkg (Get-AppxPackage | Where-Object { $_.Name -like *Ubuntu* }).PackageFamilyName Get-ChildItem $env:LOCALAPPDATA\Packages\$pkg\LocalState -Filter ext4.vhdx如果装了多个发行版可能会搜出好几个 vhdx这时候用wsl -l -v对照发行版名称或者看文件修改时间来找当前在用的那个。找到后把完整路径复制出来保存好后面 diskpart 要用。注意不要在资源管理器里直接双击挂载这个 vhdx容易让 WSL 的状态变得混乱。2.3 备份和数据清零扩容前最容易被跳过的一步很多人觉得扩容就是两条命令的事直接开干结果 diskpart 操作出错或者 WSL 启动到一半崩了才后悔没备份。我不止一次看到有人把 vhdx 搞坏之后跑来问怎么恢复这种情况下没有备份真的很难办。最稳的备份方式是用 WSL 自带的导出功能wsl --shutdown wsl --export Ubuntu-22.04 D:\wsl-backup\ubuntu2204.tar导出的 tar 文件就是整个发行版的快照几 G 到几十 G 都有可能所以要确认目标盘有足够空间。导出完成后哪怕后面磁盘操作翻车也能用wsl --import还原。如果你的数据太大、实在没有地方备份至少要把/home下的工程目录、重要配置复制出来。另外提醒一句尽量不要用wsl --unregister当备份手段那个命令会直接注销发行版并删除原始 vhdx操作不可逆。导出 tar 才是最安全的。2.4 扩容、迁移还是瘦身怎么选拿到现状之后先别急着扩容。不同情况对应的方案差别很大我一般按下面这张表来决策实际情况推荐方案理由逻辑上限不够宿主 C 盘还有充足空间diskpart 扩容 resize2fs最直接数据不动宿主 C 盘物理空间已经告急迁移到 D 盘或其他磁盘先解决宿主磁盘压力数据不多但 vhdx 文件虚胖稀疏化 / compact 瘦身不增加容量也能救急缓存和日志占了大头先清理再考虑扩容别一上来就扩逻辑上限判断逻辑很简单如果 WSL 里df -h /显示已用快满了但 C 盘还剩几百 G那放心扩容如果 C 盘本身就只剩 10G你就算把虚拟磁盘逻辑上限扩到 1T数据一写多Windows 分分钟给你表演系统盘爆红。先把方案选对后面才不会返工。3. 官方扩容实操diskpart调整VHDX并resize2fs3.1 第一步先彻底关闭WSL别只关窗口WSL 扩容最容易踩的坑就是“我以为我已经关了”。很多人只是关掉了终端窗口但 WSL 的后台进程还在跑vhdx 文件仍然被占用这时候 diskpart 操作大概率会失败或者卡住。正确的方式是执行wsl --shutdown然后再确认没有发行版在运行wsl -l -v如果这个时候看到状态还是 Running或者列表里没有出现已停止的状态检查一下 Docker Desktop 是否在后台运行。Docker Desktop 会默认使用 WSL 的发行版作为后端它不退出WSL 就没办法彻底释放。先把 Docker Desktop 退掉再执行一次wsl --shutdown然后开始下一步。3.2 第二步管理员身份运行diskpart扩容VHDXdiskpart 是 Windows 自带的磁盘工具操作虚拟磁盘需要管理员权限。开始菜单里搜 PowerShell右键“以管理员身份运行”然后输入diskpart进入 diskpart 交互界面后依次执行DISKPART select vdisk fileC:\Users\你的用户名\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu24.04LTS_79rhkp1fndgsc\LocalState\ext4.vhdx DiskPart successfully selected the virtual disk file. DISKPART expand vdisk maximum153600 100 percent completed DISKPART exit这里的153600单位是 MB也就是 150GB。注意 diskpart 里不支持直接写150GB只认数字别把 150 当目标值传进去。目标大小怎么定我习惯用当前已用空间的 1.5 到 2 倍去计算。比如现在df -h显示已用 60G目标扩到 150G那就填153600。另外路径里的用户名和包名需要替换成你实际的环境而且一定要写完整路径不能用%LOCALAPPDATA%这种环境变量。diskpart 不认。如果提示拒绝访问八成是没管理员权限如果 expand 卡住回第一步确认 WSL 是否彻底关闭。3.3 第三步回到WSL扩展文件系统diskpart 只是把虚拟磁盘的“外壳”调大了文件系统还停留在原来的容量上所以还要进 WSL 里执行 resize2fs把文件系统扩展到新容量。先启动发行版wsl -d Ubuntu-22.04然后运行df -h / lsblk重点看根文件系统挂在哪个设备上。WSL2 的通用做法是直接对整块设备做 resize但不同发行版的设备号可能不一样。比如我的 Ubuntu 24.04 是/dev/sdb有些环境会是/dev/sdc。用lsblk确认后再执行sudo resize2fs /dev/sdb如果设备名写对了一般几秒钟就能完成输出类似resize2fs 1.47.0 ... The filesystem is now 153600 blocks long.如果提示Nothing to do!说明 diskpart 扩容没生效或者你根本没有真正关闭 WSL如果提示No such device说明设备名不对回到lsblk再确认。3.4 验证并处理宿主机剩余空间扩展完之后用df -h /验证一下根目录容量看到 SIZE 从原来的 64G 变成 150G就说明成功了。整个过程不需要重启也不需要重新导入发行版所有用户和软件都还在。但这里要敲个重点扩容后 vhdx 文件不会马上就变大它只是逻辑上限变大了。真正的物理占用会随着写入数据逐渐增长。所以扩容完之后顺手检查下宿主 C 盘的剩余空间Get-PSDrive C如果 C 盘本身已经很紧张扩到 150G 反而给未来埋了雷。这种情况下我的建议是扩容完成后趁早把发行版迁移到其他盘去别让 WSL 的虚拟磁盘一直趴在系统盘里。4. 不扩容也行的替代方案把WSL搬到D盘并瘦身4.1 导出导入迁移跨磁盘最稳的方案如果你的 C 盘物理空间已经告急单纯扩容解决不了根本问题这时候应该把整个 WSL 发行版搬到 D 盘或别的分区。迁移方案我推荐用导出导入而不是在资源管理器里直接复制 vhdx 文件。直接复制文件很容易导致注册信息错乱到时候 Windows 不认这个发行版白忙一场。标准流程如下wsl --shutdown wsl --export Ubuntu-22.04 D:\wsl-backup\ubuntu2204.tar wsl --unregister Ubuntu-22.04 wsl --import Ubuntu-22.04 D:\WSL\Ubuntu2204 D:\wsl-backup\ubuntu2204.tar --version 2这里每一步都有意义export是生成发行版快照unregister是注销旧发行版并释放原 vhdx 占用的空间import是在新位置生成新的发行版。--version 2指定导入后使用 WSL2别漏掉。有一点必须反复提醒unregister是不可逆操作执行前一定要确认 tar 文件已经导出成功。怎么看看导出文件大小不要只看导出命令有没有报错。如果 tar 文件只有几 KB明显不正常先排查再继续。导入完成后旧的 tar 文件确认没问题再删。4.2 导入后恢复默认用户和文件路径用wsl --import导入的发行版默认会用 root 用户登录不会自动恢复你以前设置的那个普通用户。这时候很多人会懵怎么文件全跑 root 下面去了其实只是默认用户变了。两种恢复方式。一种是在 WSL 里给默认用户创建配置sudo tee /etc/wsl.conf EOF [user] default你的用户名 EOF然后回到 PowerShell 执行wsl --shutdown重新启动发行版默认用户就变回来了。另一种是直接用wsl -d Ubuntu-22.04 -u root进入 root 环境操作效果一样。文件路径也会变。以前 Windows 资源管理器访问的是\\wsl.localhost\Ubuntu-22.04\home\你的用户名迁移后这个路径仍然有效因为发行版名没变。如果你用了 VSCode 的 Remote-WSL重新连接一次就行。只有那些手动添加过 Windows 映射网络驱动器的旧路径需要改。4.3 给VHDX瘦身稀疏化与compact回收空间迁移只能解决“换地方”不能解决“文件虚胖”。如果你在 WSL 里清理了很多数据但 vhdx 文件在宿主机上还是很大这时候要做的就是瘦身。新版 WSL 支持直接设置稀疏属性wsl --manage Ubuntu-22.04 --set-sparse true如果版本不支持这条命令也可以在%USERPROFILE%\.wslconfig里加配置让所有 WSL2 发行版默认使用稀疏 VHD[wsl2] sparseVhdtrue改完配置记得wsl --shutdown重启才生效。稀疏化的作用是让虚拟磁盘把已经释放的块真正还回去宿主机上的 vhdx 文件会缩小到接近实际数据占用。另外diskpart 也提供了一个compact vdisk命令在 vhdx 没有被占用时可以对动态 VHD 做压缩DISKPART select vdisk fileC:\Users\你的用户名\AppData\Local\Packages\...\LocalState\ext4.vhdx DISKPART compact vdisk先说清楚瘦身要在清理完 WSL 内部数据之后做否则释放不了多少空间。而且这个操作对 I/O 性能理论上有一点影响实际使用中我基本感知不到不用太担心。5. 扩容避坑指南常见报错与排查记录5.1 找不到ext4.vhdx搜索出来好几个怎么办如果你装了多个 WSL 发行版比如 Ubuntu、Ubuntu-22.04、Ubuntu-24.04甚至还有 Docker Desktop 配套的docker-desktop-data搜索ext4.vhdx就会列出多个文件。这时候千万别随便挑一个就扩容改错了发行版的磁盘轻则 Docker 崩重则自己项目全丢。最稳妥的办法是先用wsl -l -v确认当前在用的发行版名称再回到找路径那一步按 PackageFamilyName 对应。如果还不放心就看文件的修改时间最近更新过、文件体积最大的那个通常就是你在用的。Docker Desktop 的 vhdx 路径比较特殊如果目标是给 Docker 的数据盘扩容记得先退出 Docker Desktop再定位docker-desktop-data对应的 vhdx操作思路一样但别和 Ubuntu 的搞混。5.2 resize2fs提示设备不存在或容量没变这个问题出现的频率极高。先说设备不存在多半是你把/dev/sdb当默认值填了但当前发行版实际挂载的是/dev/sdc。解决办法很简单别猜直接用命令拿df -h / lsblk看根目录挂载点对应的设备名然后拿那个设备名去执行sudo resize2fs /dev/设备名。再说容量没变。最常见的原因是 WSL 没有真正关闭diskpart 扩容没有成功写入。处理方法是回到 PowerShell执行wsl --shutdown确认没有发行版处于 Running 状态再重新走 diskpart 流程。还有一种是expand vdisk maximum的目标值比当前容量小这种情况 diskpart 会直接报错把目标值改成大于当前容量即可。5.3 扩容后WSL无法启动如何恢复说实话正常流程下我没怎么遇到过扩容后 WSL 起不来的情况但总有各种意外。如果扩容之后wsl -d启动不了先别慌按顺序排查。先执行wsl --shutdown然后再启动很多临时性占用问题靠这一步就解决了。如果还不行检查一下杀毒软件或安全工具是不是在后台锁定了 vhdx 文件。再不行就看原 vhdx 文件是否还在、大小是否异常。如果 diskpart 过程中报过错文件可能已经损坏这时候前面让你做的 tar 备份就派上用场了用wsl --unregister注销当前发行版再wsl --import从备份恢复。没有备份的情况下尽量不要反复强制关机或者强行删除 vhdx那只会让情况更糟。这也是我在第 2 章反复强调备份的原因。磁盘操作这种东西平时觉得多余真出事就知道救命了。5.4 常见问题速查表症状原因处理方法diskpart 提示拒绝访问不是管理员身份运行右键以管理员身份打开 PowerShellexpand 卡住或失败vhdx 被 WSL 或 Docker 占用执行wsl --shutdown退出 Docker启动 WSL 后容量没变没运行 resize2fs或没有真正 shutdown按“关闭-扩容-resize2fs”顺序重来resize2fs 提示 No such device根设备名不对用lsblk或df -h /确认设备名清理数据后 C 盘空间没少虚拟磁盘没收缩稀疏化或compact vdisk导入后默认是 root 登录默认用户被重置写/etc/wsl.conf设置 default 用户迁移后文件路径找不到发行版路径变化用\\wsl.localhost\发行版名访问wsl命令本身不识别WSL 组件没装好先重新安装和配置 WSL 基础组件再扩容最后分享一个我自己保留的习惯每次扩容前先看两样东西——宿主 C 盘剩余空间和 WSL 内部的df -h /。前者决定你能不能扩后者决定你要扩到多少。别等apt upgrade都跑不动才处理那时候连导出备份都会变得很痛苦。我一般会在 WSL 用到 70% 左右就顺手做一次扩容或者瘦身把流程写成笔记C 盘就不会突然告急。这套操作我走了一遍又一遍核心就是“完全关闭、diskpart 扩容、resize2fs 收尾”剩下的都是细节。
返回列表