WSL 磁盘空间救火手册:VHDX、Docker、模型缓存和真正能回收的空间
原创 · 约 17 分钟阅读 · 阅读 --

WSL 磁盘空间救火手册:VHDX、Docker、模型缓存和真正能回收的空间

作者: Alex Xiang


古董级程序员,大厂出来后一直在创业公司,现在仍活跃在一线做 AI 相关的开发。更完整的更新写在微信公众号「字与码」:工作经历、对新技术的想法,以及这些年走弯路的记录,会不定期发在那里。若觉得博客对你有用,欢迎顺手关注。

WSL 最容易让人崩溃的问题之一,是 C 盘突然满了。

你在 Ubuntu 里删了几十 GB 文件,df -h 看起来空出来了。回到 Windows 一看,C 盘还是没少。再打开目录,发现某个 ext4.vhdx 仍然巨大。

这不是错觉。WSL2 的 Linux 文件系统在 Windows 里通常是一个虚拟硬盘文件。Linux 里面删文件,只是让虚拟硬盘内部有了空闲块;Windows 看到的 VHDX 文件,不一定会立刻缩小。

WSL 磁盘空间、VHDX、Docker 和模型缓存清理

这篇从一次真实的救火流程写起:开发机 C 盘只剩 2GB,WSL 里跑不动 Docker,Node 项目装依赖失败,本地模型也没法下载。目标不是炫技,而是把“查什么、删什么、怎么确认真的回收了”说清楚。

第一件事:分清 Linux 里空了,还是 Windows 里空了

先在 WSL 里看:

df -h

看当前发行版根文件系统:

df -h /

再看大目录:

du -h -d 1 ~ | sort -h
sudo du -h -d 1 /var | sort -h

如果装了 Docker:

docker system df

如果跑本地模型:

du -sh ~/.cache ~/.ollama ~/models 2>/dev/null

这些命令回答的是:Linux 内部是谁占了空间。

Windows 侧要看 VHDX。默认商店版 Ubuntu 的路径通常在:

%LOCALAPPDATA%\Packages\CanonicalGroupLimited.Ubuntu...\LocalState\ext4.vhdx

不同发行版名字不一样。可以在 PowerShell 里查:

wsl -l -v

再到 %LOCALAPPDATA%\Packages 里看对应发行版目录。

这里的关键是:du 变小,不代表 ext4.vhdx 立刻变小。

先删确定无害的东西

我会从低风险缓存开始。

apt 缓存:

sudo apt clean
sudo apt autoremove --purge -y

Python 缓存:

find ~ -type d -name '__pycache__' -prune -exec rm -rf {} +
find ~ -type d -name '.pytest_cache' -prune -exec rm -rf {} +

Node 项目的依赖不要全局乱删,先找:

fd -H '^node_modules$' ~/work -t d \
  | xargs -r du -sh \
  | sort -h

确认某些老项目不再需要,再删:

rm -rf ~/work/old-project/node_modules

Rust、Go、pnpm、Yarn、npm 也常见:

du -sh ~/.cargo ~/.cache/go-build ~/go/pkg/mod ~/.npm ~/.pnpm-store ~/.cache/yarn 2>/dev/null

不要一条 rm -rf ~/.cache 了事。很多工具缓存删了可以重建,但有些缓存里混着登录状态、下载中的模型、构建索引。先看清楚。

Docker 是空间黑洞,但也最容易误删

Docker 的空间占用要单独看:

docker system df

列出镜像:

docker image ls

列出卷:

docker volume ls

清理停止容器、未使用网络、悬空镜像:

docker system prune

如果确定未使用镜像也可以删:

docker system prune -a

卷最危险。很多数据库数据都在 volume 里。不要随手:

docker volume prune

除非你确认这些卷不含需要保留的数据。

我通常先输出一份清单:

docker system df -v > docker-space-before.txt

清理后再:

docker system df -v > docker-space-after.txt

这样出了问题至少知道删过什么。

本地模型缓存要设“仓库”,不要散养

AI 开发机很容易被模型缓存吃满。

常见位置:

du -sh ~/.cache/huggingface ~/.ollama ~/models 2>/dev/null

Hugging Face:

export HF_HOME="$HOME/models/huggingface"
export TRANSFORMERS_CACHE="$HF_HOME/transformers"
export HF_DATASETS_CACHE="$HOME/datasets/huggingface"

Ollama:

du -sh ~/.ollama 2>/dev/null
ollama list

如果模型不再需要,优先用工具自己的命令删:

ollama rm qwen2.5:7b

不要直接在模型目录里乱删单个 blob。很多模型管理器会用内容寻址、引用计数或 manifest。手工删除容易留下半残状态。

我会给本地 AI 项目定一个目录规范:

~/models/       # 模型权重
~/datasets/     # 数据集
~/runs/         # 实验输出
~/archive/      # 可清理归档

然后每周看一次:

du -h -d 1 ~/models ~/datasets ~/runs 2>/dev/null | sort -h

删除后,为什么 Windows C 盘还是没变小

因为你只是让 ext4 文件系统内部出现空闲块。VHDX 文件本身仍然可能保持原大小。

Microsoft 的 WSL 磁盘空间文档里提供了管理和调整虚拟磁盘大小的方法。新版 WSL 可以用:

wsl --manage <Distro> --resize <Size>

但“扩容”和“回收宿主空间”是两件事。扩容是让虚拟磁盘可用上限变大;回收是让 Windows 上的 VHDX 文件变小。

回收前先关掉 WSL:

wsl --shutdown

然后再按 Windows 版本和 WSL 版本选择方式。

有些环境可以依赖 WSL 的稀疏 VHD 支持,有些环境需要用 Optimize-VHDOptimize-VHD 属于 Hyper-V 模块,不是所有 Windows 版本默认可用。

如果你能用:

Optimize-VHD -Path "C:\path\to\ext4.vhdx" -Mode Full

执行前一定确认路径是对应发行版的 VHDX,并且 WSL 已经 shutdown。

如果环境不支持这个命令,保守办法是导出/重新导入发行版:

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

这条路风险更高,因为 --unregister 会删除原发行版。做之前必须确认导出文件可用、有备份、知道如何恢复。不要在半夜 C 盘 0 字节时第一次尝试。

给自己做一个巡检脚本

我会放一个 ~/bin/wsl-space-report

#!/usr/bin/env bash
set -euo pipefail

echo "== filesystem =="
df -h /
echo

echo "== home top =="
du -h -d 1 "$HOME" 2>/dev/null | sort -h | tail -20
echo

echo "== work node_modules =="
fd -H '^node_modules$' "$HOME/work" -t d 2>/dev/null \
  | xargs -r du -sh \
  | sort -h \
  | tail -20
echo

echo "== model caches =="
du -sh "$HOME/.cache/huggingface" "$HOME/.ollama" "$HOME/models" "$HOME/datasets" 2>/dev/null || true
echo

if command -v docker >/dev/null 2>&1; then
  echo "== docker =="
  docker system df || true
fi

加执行权限:

chmod +x ~/bin/wsl-space-report

每次 C 盘变红,先跑它。不要凭感觉删。

我自己的清理顺序

我的顺序通常是:

  1. wsl-space-report 找大头;
  2. 清理 apt、Python、测试缓存;
  3. 清理废弃项目的 node_modules.venv
  4. docker system df -v 看镜像和卷;
  5. 删除不用的模型;
  6. 归档 ~/runs 和大数据集;
  7. wsl --shutdown
  8. 必要时压缩或迁移 VHDX。

不要反过来,一上来就压缩 VHDX。内部垃圾没清掉,压缩也没意义。

什么时候该重建一个干净发行版

如果一个 WSL 用了两三年,里面有无数项目、老版本语言运行时、废弃数据库、散落的模型和半残 Docker 卷,清理有时候不如重建。

做法是:

wsl --export Ubuntu D:\backup\ubuntu-old.tar
wsl --install -d Ubuntu

新发行版里只迁移:

  • ~/work 里仍在维护的项目;
  • .ssh.gnupg 等明确需要的配置;
  • dotfiles;
  • 必要的模型和数据;
  • 脚本工具。

重建不是逃避,是把多年堆积的临时状态清掉。

小结

WSL 磁盘问题最容易让人误判,因为它有两层空间:

Linux 里面的空闲空间。
Windows 看到的 VHDX 文件大小。

清理要先在 Linux 里找到真正占用者,再决定删缓存、删依赖、删镜像、删模型还是迁移数据。内部清干净后,再考虑回收 VHDX。

不要把“C 盘满了”当成一个单点问题。它通常是开发习惯的结果:项目放哪、Docker 怎么用、模型缓存怎么管、归档有没有做。

参考资料: