C 盘爆红这件事,我已经不是第一次经历了。这次为了把 openclaw 的本地开发环境完整跑起来,我又被 WSL2 的虚拟磁盘折磨了一回,最后不得不把整个 WSL2 发行版从 C 盘搬迁到 D 盘,顺手装上了 Node.js 24,才终于把环境稳定下来。如果你也在折腾 openclaw,同时对 C 盘空间告急这件事非常头疼,那么这篇文章应该能帮你少走很多弯路。
先说下背景。openclaw 是一个偏个人工作流方向的开源智能助手框架,核心思路是用 Node.js 把本地笔记、聊天应用、任务工具串起来,让它们之间可以互相触发。它不是一个单纯聊天的“壳子”,更像是一个事件驱动的自动化中枢,可以接 Microsoft Teams、Obsidian,也能自己定义技能和工作流。因为涉及大量异步事件、WebSocket 长连接和本地文件监听,它需要一个真正的 Linux 环境,一个较新的 Node.js 运行时,最好还能用 systemd 或进程守护工具让服务稳定常驻。这三样东西正好是 WSL2 的强项。
1. 为什么非搬不可:C 盘空间与 WSL2 的那些账
1.1 openclaw 是个什么项目,为什么值得本地折腾
openclaw 跟很多现成的 AI 助手项目不一样,它不提供一套固定功能的客户端,而是给你一整套可以自定义的“工作流骨架”。你在配置里声明好触发条件,比如“Teams 收到某个关键词的消息”或者“Obsidian 里新生成了一篇笔记”,openclaw 就会把这些事件拉起来,按你预设的流程去执行,可能调用一个本地脚本,也可能调用外部 API,再把结果通过 Teams 或笔记插件返回。
这种依赖事件驱动的架构,对运行环境的要求很明确:文件系统事件监听要可靠,网络端口要能稳定监听,如果涉及并发任务调度,还需要运行时对异步 IO 支持得好。在 Windows 上,文件监听事件丢失是出了名的老大难,权限模型也经常让 Node.js 项目在读取某些目录时报错。我在 PowerShell 里部署过一次,项目能启动,但 Obsidian 文件触发经常延迟甚至不触发,后来切到 WSL2 之后,问题基本消失。原因很简单:openclaw 对 Linux 原生文件系统和 Node.js 的fs.watch依赖太深,Windows 的文件系统事件模型跟 Linux 有很大差异,这种项目天然生存在 Linux 环境里更合适。
1.2 C 盘被吃掉的“罪魁祸首”并不只有源码
很多朋友以为 C 盘空间不足是源码工程太大,其实源码加依赖也就几百 MB 到 1GB 左右,真正的空间黑洞往往藏在下面几处:
- WSL2 的虚拟磁盘文件,也就是
ext4.vhdx。它挂在%LOCALAPPDATA%\Packages\...\LocalState\下面,会随着发行版里安装的软件、日志、容器镜像持续增长。我装完 openclaw 的各种依赖和构建工具后,这个文件一度膨胀到 30 多 GB。 - Node.js 的 npm 全局缓存。npm 默认把缓存放在用户目录,而 WSL2 的用户目录在发行版虚拟磁盘内部,等于还是在 C 盘。
- Docker Desktop 的数据。WSL2 里跑 Docker 容器、拉镜像、存储数据,默认也都塞在虚拟磁盘里。
- openclaw 运行时的日志、临时文件、本地向量数据。这部分增量不大,但日积月累也挺可观。
把这些加起来,一个看似轻量的开发环境吃 40GB 一点不夸张。对系统盘不宽裕的人,唯一的靠谱方案就是把整个 WSL2 发行版迁走,然后把各类缓存路径也重新规划到 D 盘。
1.3 为什么选 WSL2,而不是虚拟机或者纯 Windows 方案
有人可能问,既然要占空间,为什么不用 Windows 自带的 Hyper-V 虚拟机,或者 VirtualBox?传统虚拟机要给整个系统留固定大小的磁盘镜像,启动一个完整 Linux 桌面对内存和 CPU 开销都很大,日常使用太笨重。WSL2 不一样,它共享 Windows 的内核服务和文件系统桥接,启动一个发行版就跟打开一个终端一样快,内存占用也远低于一整个虚拟机。而对 openclaw 来说,WSL2 提供的 Linux 内核已经足够跑 Node.js 服务、监听端口、操作文件系统,省掉的复杂度反而能让环境更清爽。
最终方案也就确定下来:Windows 做桌面,openclaw 的开发运行环境全部放进 WSL2,再把 WSL2 的虚拟磁盘从 C 盘迁到 D 盘。这样系统盘不再吃紧,又能享受完整的 Linux 生态。下面就从搬迁开始一步步来。
2. WSL2 发行版搬迁实操:从 C 盘挪到 D 盘
2.1 搬迁前先摸清底细
先别急着搬,搞清楚现状再说。打开 Windows Terminal 或 PowerShell,执行:
wsl --list --verbose这会列出你当前安装的所有发行版,名字后面带 * 的是默认发行版,VERSION 一列会显示当前是 WSL1 还是 WSL2。如果你之前装过一个旧的 Ubuntu,还在 WSL1 模式,建议先手动升级到 WSL2 再迁移,避免后面出现版本混乱的问题。
VERSION 确认之后,再找到 ext4.vhdx 的实际位置。打开文件资源管理器,进入:
%LOCALAPPDATA%\Packages\CanonicalGroupLimited.Ubuntu..._*\LocalState\不同发行版的 PackageFamilyName 会不一样,找类似 “Ubuntu” 或 “Debian” 的目录就行。里面的ext4.vhdx就是完整虚拟磁盘,右键看属性就知道它占了多少空间。这一步一定要做,因为仅凭“我感觉没装多少东西”来判断,往往会漏掉已经膨胀到几十 GB 的镜像。
另外,如果发行版里已经跑了 openclaw,记得提前把配置目录、工作数据、.env文件额外复制一份到 D 盘。export tar 包虽然会包含全部数据,但多做一道手工备份,迁移时心里踏实很多。
2.2 export / import 三步迁移法
WSL2 的官方迁移方式是“导出再导入”,不能直接把 vhdx 文件复制到 D 盘。直接复制会导致 WSL 不认这个路径,还可能在下次启动时损坏发行版。正确流程分三步走。
第一步,关闭所有 WSL 会话。在 PowerShell 里执行:
wsl --shutdown第二步,导出发行版。以默认的 Ubuntu 为例:
wsl --export Ubuntu D:\wsl-backup\ubuntu-full.tar如果你发行版不叫 Ubuntu,先通过wsl --list查实际名字。导出过程根据 vhdx 大小可能要几分钟到十几分钟,期间别乱开 WSL 窗口,也别把这个 PowerShell 关掉。
第三步,注销原发行版,释放 C 盘空间:
wsl --unregister Ubuntu这一步会从已安装列表里移除 Ubuntu 并删除 C 盘上的 vhdx。请务必定确认上一步的 tar 包已经完整导出。我第一次迁移时就是因为 tar 还没导完就取消命令,好在原发行版还在,没造成数据丢失。第二次老老实实等导出完成也没花太久,毕竟一次性把 30 多 GB 搬走才安逸。
注销之后,在 D 盘创建目标目录,例如D:\wsl\Ubuntu,再执行导入:
wsl --import Ubuntu D:\wsl\Ubuntu D:\wsl-backup\ubuntu-full.tar --version 2这个命令有两个路径,第一个是将来 vhdx 的存放位置,第二个是刚才导出的 tar 包。导入完成后用wsl --list --verbose检查,Ubuntu 的 VERSION 应该显示 2。到这里,发行版主体已经从 C 盘挪到 D 盘了。
2.3 迁移后必做的三件事
迁移完不是直接开干,有三件事必须做,否则后面大概率会踩坑。
第一件,解决默认用户问题。export / import 之后默认登录用户会变成 root。如果一直用 root 操作,后面 openclaw 创建的文件、Obsidian 插件生成的缓存权限会全部变成 root 所有,普通用户再想去改就很麻烦。解决办法是先启动一次 Ubuntu,然后用命令设置默认用户:
ubuntu.exe config --default-user 你的用户名更通用的方式是在 WSL 内编辑/etc/wsl.conf:
[user] default=你的用户名然后从 Windows 执行wsl --shutdown,再重新进入 WSL,默认用户就恢复了。
第二件,检查文件系统是否正常。执行df -h,确认根目录挂载点和可用空间没有问题。第三件,检查 openclaw 源码和配置路径有没有问题。导入后相对路径通常不变,但如果有 git 子模块,偶尔会因为路径引用问题失效,建议进入项目目录执行git submodule status看一眼。
2.4 顺手把缓存目录也搬到 D 盘
迁完 vhdx,C 盘空间会释放一大块,但如果 npm 缓存、Docker Desktop 数据还留在默认位置,后续还是会一点一点蚕食系统盘。建议趁热打铁,把这些缓存路径统一规划到 D 盘。
npm 缓存可以在 WSL 内修改~/.npmrc:
cache=/mnt/d/wsl-cache/npm全局包安装目录也可以一起改:
npm config set prefix "/mnt/d/npm-global"Docker Desktop 的数据目录需要在 Docker Desktop 设置里的 Resources 页面,把 Disk image location 改成 D 盘路径。这样以后 Docker 拉取镜像和存储容器数据,都不再触碰系统盘。别小看这一步,很多人迁完发行版,结果 Docker 还在 C 盘闷头写入,过两周又红了。
3. 为什么是 Node.js 24:版本选择与安装完整流程
3.1 openclaw 对 Node.js 版本的隐性要求
openclaw 这类同时处理 WebSocket、文件监听、任务调度的项目,对 Node.js 版本其实相当敏感。它内部用了不少较新的异步 API 和 stream 行为改进,在我看来,版本太低确实会触发各种诡异的运行时错误。我最初在 WSL2 里用的是 Ubuntu 自带源里的 Node.js 18,跑 openclaw 构建脚本时频繁遇到依赖版本不匹配的报错,切换到 Node.js 24 之后立刻安静了。
Node.js 24 目前处于 LTS 维护周期,是当前环境里安全性和稳定性都兼顾的版本线。对本地开发来说,它自带的特性支持、日常性能、调试体验都足够好。尤其是事件驱动的服务,Node 24 对并发和异步 IO 的调度优化比早期版本明显更平滑,openclaw 这种“多路事件同时进来”的场景跑起来更从容。
3.2 用 nvm 安装 Node.js 24
在 WSL2 里安装 Node.js,我强烈建议用 nvm,而不是直接下载 Linux 安装包或者用系统 apt 源。nvm 允许你在同一个环境里随意切换多个 Node 版本,openclaw 以后升级要求更高版本时,直接nvm install 新版本切过去就行,不用折腾系统级安装器。
在 Ubuntu 终端里执行:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash如果当前网络环境访问官方脚本地址不顺畅,也可以用公共镜像源下载这份脚本,本质是一样的。安装完成后重开终端,或者手动执行:
source ~/.bashrc然后安装 Node.js 24:
nvm install 24 nvm alias default 24 nvm use 24验证版本:
node -v npm -v如果输出是 v24 开头的版本号,说明安装成功。此时用which node确认路径落在 nvm 管理的目录下,不要是/usr/bin/node这种系统路径,否则后续nvm use切换不会生效。
3.3 corepack 启用 pnpm,并配置依赖下载速度
openclaw 这类项目大多使用 pnpm 作为包管理器,因为 pnpm 通过硬链接和内容寻址存储,在依赖树很大时的空间占用和安装速度都有优势。Node.js 24 自带 corepack,完全不需要单独装 pnpm:
corepack enable corepack prepare pnpm@latest --activate pnpm --version如果 corepack 报权限错误,试试用sudo corepack enable或者先把用户目录权限理顺。然后设置 npm 和 pnpm 的镜像源:
npm config set registry https://registry.npmmirror.com pnpm config set registry https://registry.npmmirror.com这一步不是必须的,但对国内网络环境来说几乎等于必做。镜像源只优化下载速度,不会改变依赖本身的内容,安装行为是安全的。
4. openclaw 本地部署:从拉取代码到接入 Teams / Obsidian
4.1 源码部署和 Docker 一键部署怎么选
openclaw 给用户提供了两条常见部署路径:一种是本地一键部署的 Docker Compose 方式,会自动拉起数据库和运行时;另一种是基于源码的 Node.js 部署方式。Docker 部署省事,但你已经手动搭好了 WSL2 + Node.js 24,我建议直接用源码方式部署。源码部署的好处是调试方便,项目结构一目了然,改完代码重启一下就能看到效果,对理解 openclaw 的工作流机制特别有帮助。
进入代码目录并拉取仓库:
mkdir -p ~/projects && cd ~/projects git clone https://github.com/你的fork/openclaw.git cd openclaw pnpm install如果你不确定仓库地址,在搜索引擎里搜 openclaw 官方仓库即可。pnpm install过程中如果报 node-gyp 编译错误,通常是缺少编译工具链,先执行:
sudo apt update sudo apt install build-essential python3装完再重新执行pnpm install。这一步在干净的 WSL2 环境里几乎都会碰到,不用慌,装了再跑一遍就好。
4.2 构建和启动 openclaw
依赖装完后,通常要先执行构建命令,把 TypeScript 编译成 JavaScript。openclaw 的项目脚本一般会提供pnpm build,启动命令可能是pnpm start或者pnpm dev。具体以项目 README 为准,但整体流程是一致的:
cp .env.example .env # 编辑 .env,配置端口、数据库连接、密钥等 pnpm build pnpm start启动后看到类似 “Server listening on port 3000” 的日志,说明服务已经起来了。此时在 Windows 浏览器访问http://localhost:3000,WSL2 的 localhost 转发机制会自动帮你映射到 WSL 内的服务。如果访问不到,先检查服务有没有监听0.0.0.0,再检查 Windows 防火墙是否拦截了 WSL 的流量。
这里补一句:如果你后续打算在 openclaw 里调用本地模型做推理,WSL2 天然支持 NVIDIA CUDA 加速,Windows 侧装好显卡驱动后,WSL 内直接识别 GPU,不需要额外安装任何驱动。这一步可以放到环境调优时再搞,搭建阶段先专注把服务跑通。
4.3 接入 Microsoft Teams 的配置要点
openclaw 与 Microsoft Teams 联动,是很多人最想玩的部分。这里提醒一下:接入 Teams 的关键不在 openclaw 侧,而在微软开发者后台的应用注册。你需要先在 Microsoft Teams 开发者平台创建一个 Bot 应用,拿到 Tenant ID、Client ID、Client Secret,并配置 Bot 的消息回调地址指向 openclaw 对外暴露的接口。
本地开发没有公网地址,通常需要借助内网穿透工具或者直接在服务器上部署,生产环境也会走 HTTPS 回调。在 openclaw 的.env里,配置项大致如下:
TEAMS_TENANT_ID=你的TenantId TEAMS_CLIENT_ID=你的ClientId TEAMS_CLIENT_SECRET=你的ClientSecret TEAMS_REDIRECT_URI=http://localhost:3000/auth/teams/callbackMicrosoft Teams 平台对回调地址有严格规则,纯本地测试时可以用 localhost 白名单。如果一直报 unauthorized,优先检查三件事:Client Secret 是否复制完整、回调地址是否与应用注册页面完全一致、.env改完后是否重启了服务。我见过太多因为.env改完没重启就反复排查配置的例子。
4.4 接入 Obsidian 的配置要点
openclaw 联动 Obsidian,核心需求就是让 openclaw 能读取 Obsidian vault 里的笔记或者监听文件变化。Obsidian 本身没有官方对外 HTTP API,需要安装社区插件来提供本地 REST API。在 Obsidian 里启动对应插件,设置一个 API Key,然后在 openclaw 配置里填入三项信息:
- Vault 路径,也就是 Obsidian 仓库在 WSL 里的路径,比如
/mnt/d/ObsidianVault - API Base URL,默认通常是
http://localhost:27124 - API Key,插件生成的那串密钥
配置完成后,可以试一条简单规则,比如“当 Obsidian 新增标题包含 TODO 的笔记时,调用某个脚本”。如果联动没反应,先查路径权限。从 WSL 访问/mnt/d/下的 Windows 文件需要转换路径,速度会慢一点,但读写正常。注意别把 Windows 路径D:\ObsidianVault直接填进去,WSL 里必须写成/mnt/d/ObsidianVault格式。
4.5 让 openclaw 在 WSL2 里稳定常驻
启动 openclaw 只是第一步,让它长期稳定跑着才是第二步。WSL2 的终端一旦关闭,前台运行的服务就会退出,所以我建议把 openclaw 交给 systemd 托管。新版 WSL2 支持在/etc/wsl.conf里开启 systemd:
[boot] systemd=true然后创建一个 systemd service 文件,比如/etc/systemd/system/openclaw.service:
[Unit] Description=openclaw service After=network.target [Service] User=你的用户名 WorkingDirectory=/home/你的用户名/projects/openclaw ExecStart=/home/你的用户名/.nvm/versions/node/v24.x.x/bin/node server.js Restart=always RestartSec=10 [Install] WantedBy=multi-user.target注意ExecStart里的 Node 路径,要以which node实际输出为准,不要照抄我的。然后执行:
sudo systemctl daemon-reload sudo systemctl enable openclaw sudo systemctl start openclaw用 systemd 而不是 nohup 的好处很直接:崩溃自动拉起、开机自启、日志统一用journalctl查看,对长期运行的服务来说省心太多。如果你的 WSL 版本不支持 systemd,用 pm2 也能达到类似效果,二选一就行。
5. 常见问题与踩坑排查清单
5.1 迁移和安装阶段最常见的 8 个问题
整理一下我折腾过程中遇到的高频问题,基本覆盖新手阶段 80% 的报错:
| 现象 | 可能原因 | 处理办法 |
|---|---|---|
| wsl --list --verbose 显示 VERSION 为 1 | 发行版还在 WSL1 模式 | wsl --set-version Ubuntu 2 |
| 迁移导入后默认用户变成 root | export / import 不保留默认用户 | 用ubuntu.exe config --default-user 用户名或修改 /etc/wsl.conf |
| WSL 启动报 0xffffffff | WSL 内核版本过旧或虚拟化未开启 | wsl --update,重启电脑,检查 BIOS 的虚拟化开关 |
| pnpm install 报 node-gyp 编译错误 | 缺少 build-essential 和 python3 | sudo apt install build-essential python3后重装 |
| npm 和 pnpm 下载依赖速度极慢 | 默认 registry 是官方源 | 设置 registry 为 npmmirror 镜像 |
| Windows 浏览器访问 localhost:3000 失败 | 服务监听 127.0.0.1 或防火墙拦截 | 让服务监听 0.0.0.0,检查 Windows Defender 防火墙 WSL 规则 |
| WSL 内存占用过高,Windows 卡顿 | WSL2 默认可使用全部内存 | 在/mnt/c/Users/你的用户名/.wslconfig里限制 memory 和 processors |
| openclaw 服务启动后一直重启 | .env 配置项不完整或端口被占用 | 查看 systemd 日志sudo journalctl -u openclaw -f,检查端口占用 |
5.2 一个隐蔽的坑:C 盘又快满了,根源却是 Docker 镜像
这是个很容易被忽略的事。你以为 WSL2 发行版搬到 D 盘就万事大吉,结果过了两周 C 盘又红了。查下来发现,Docker Desktop 的数据目录还是在默认的 C 盘位置。如果你打算用 Docker 方式跑 openclaw 或它依赖的数据库,一定要在 Docker Desktop 设置里把 Disk image location 改到 D 盘。Docker Desktop 运行状态下修改这个路径,会自动把现有虚拟磁盘迁移过去。搬完之后再检查一次 C 盘空间,释放效果肉眼可见。
5.3 另一个容易踩坑的点:项目文件放 /mnt/d/ 还是放 /home/
openclaw 的源码和运行数据,我建议放在 WSL2 的文件系统内部,也就是 /home 目录,不要放在/mnt/d/这种跨文件系统挂载路径上。虽然/mnt/d/也能正常读写,但每一次文件操作都要经过 9P 协议跨系统转发,npm install 这种动辄几万次小文件操作的场景会被拖慢好几倍。Obsidian vault 因为是 Windows 文件,只能放在/mnt/d/,这部分单次读取可以接受。但 openclaw 工程本体、Node 依赖、缓存这些高频读写的内容,一律放到 Linux 内部路径。因为整个发行版已经搬到 D 盘,所以 /home 下的项目文件并不占 C 盘空间,运行速度还快,两全其美。
踩过几次坑之后,我现在的习惯是:WSL2 发行版放 D 盘,openclaw 工程在 /home 下,Obsidian vault 在 /mnt/d/ 下,npm / pnpm 缓存和 Docker 镜像也都指向 D 盘。迁一次把盘符规划好,后面基本不用再操心 C 盘空间的问题。如果你也准备搭这套环境,建议先把这几个路径规划清楚再动手,省下来的时间和心情,足够你多折腾几个 openclaw 的玩法和技能了。