WSL 的 ext4.vhdx 虚拟硬盘是动态扩展的——文件删了它不会自动缩小。装过 CUDA、Torch 等大包后,uv 缓存即使清理了,C 盘空间也不会回来,必须手动压缩 vhdx 文件


适用场景

  • C 盘空间告急(剩余 < 20 GB)
  • 刚清了一大波 WSL 内部文件(如 uv cache clean、删大文件等)
  • WSL 内部 df -h 显示空间充足,但 Windows C 盘没变化

原理

WSL 内部删除文件
    ↓
sudo fstrim -v /        ← 通知虚拟硬盘:这些块可以回收了
    ↓
wsl --shutdown           ← 关掉 WSL 才能动 vhdx 文件
    ↓
diskpart compact vdisk   ← 物理压缩 vhdx 文件大小
    ↓
C 盘空间归还

操作步骤(全程约 5 分钟)

第一步:停止 WSL 服务

关掉所有正在使用 WSL 的程序(Web UI、终端等)。

第二步:TRIM 操作(告诉 vhdx 哪些块能回收)

在 Ubuntu 终端中执行:

sudo fstrim -v /

预期输出示例:

/: 983.2 GiB (1055743963136 bytes) trimmed

第三步:关闭 WSL

wsl.exe --shutdown

或者直接关闭所有 Ubuntu 终端窗口。

第四步:压缩 vhdx 文件

打开 Windows 的 cmd(以管理员身份运行),依次输入:

diskpart
select vdisk file="C:\Users\zzgsh\AppData\Local\wsl\{ea28b0f4-4218-4d15-a729-08eb831e0460}\ext4.vhdx"
attach vdisk readonly
compact vdisk
detach vdisk
exit

⚠️ vhdx 的实际路径可能因 WSL 版本不同而变化。如果找不到文件,可以在 cmd 中运行: dir /s /b C:\*.vhdx

压缩过程通常几秒钟到几十秒,等待 diskpart 返回提示即可。

第五步:验证

重新打开 Ubuntu,检查 C 盘剩余空间:

df -h /mnt/c

第六步:重启 Web UI(如果用的话)

cd ~/hermes-webui && python3 server.py

效果参考

按本手册操作一次,在清完 uv 缓存(~21 GB)的情况下:

项目操作前操作后
vhdx 文件大小35 GB~11 GB
C 盘剩余~17 GB~40 GB
WSL 内部使用~10 GB不变

常见问题

Q: diskpart 提示”虚拟磁盘不支持此操作”

虚拟机磁盘文件必须是 动态扩展 类型才能 compact。wsl --import 导入的 vhdx 默认就是动态扩展,一般不会遇到这个问题。

Q: 压缩后 WSL 网络配置会变吗?

不影响。compact 只是文件层面的压缩,不改动注册表或网络配置。

Q: 每次清理大文件后都要做吗?

不是。只有当 C 盘空间紧张时才需要。fstrim 可以随时跑(不关机也可以),但只有配合 compact 才能真正归还 C 盘空间。

Q: 不想这么折腾,有什么一劳永逸的办法?

把 WSL 虚拟硬盘迁移到 D 盘。步骤:

  1. wsl --shutdown
  2. 复制 vhdx 到 D 盘
  3. wsl --unregister Ubuntu
  4. wsl --import Ubuntu D:\WSL\ D:\WSL\ext4.vhdx
  5. 重设默认用户 但迁移后镜像网络模式需要重新配置。

本文对应的错误教训:Hermes Agent 无法直接执行 sudo(需要终端交互)和 diskpart(需要 Windows 管理员 cmd),所以这个操作只能手动完成。