上个月我决定把 OpenClaw 真正用起来,结果发现最耗时的事情不是调模型,而是在 Windows 上把环境跑通。OpenClaw 这类开源智能体框架,官方文档默认你有一台 Linux 服务器,可我的主力机就是 Windows。中文资料少得可怜,零零散散搜下来,全是什么安卓部署、ROS2 联动、Skill 开发,完整可用的 Windows 踩坑指南几乎没有。我硬是折腾了三天,把 WSL、Node、Python、Poetry、Ollama、systemd 这些环节全部趟了一遍,才让 OpenClaw 稳定跑起来。
这篇文章就当作我个人的踩坑记录,覆盖从 WSL 初始化、OpenClaw 安装配置、模型接入、服务化托管到故障排查的完整链路。适合的目标读者非常明确:手头只有 Windows 电脑、想本地跑 OpenClaw 做个人助理或自动化工作流、但不想折腾虚拟机双系统的朋友。如果你属于这类人,这篇指南应该能帮你省下至少两天的试错时间。
1. 为什么在 Windows 上跑 OpenClaw,我最终选择了 WSL
1.1 OpenClaw 在 Windows 原生环境跑不起来的真实原因
很多朋友下载完 OpenClaw 就想在 PowerShell 里直接跑,这是第一道坎。OpenClaw 的核心运行时大量依赖 Linux 生态,比如 bash 脚本编排、inotify 文件监听、systemd 进程托管、Python 源码包编译所需的完整 GCC 工具链,这些在 Windows 原生环境下要么残缺,要么行为完全不一样。
具体来说,OpenClaw 的 Skill 系统会自动监听某个目录的文件变化,Windows 原生虽然有 ReadDirectoryChangesW,但和 inotify 的事件语义差异很大,很多 Skill 在 Windows 上要么监听不到事件,要么偶尔触发但拿不到正确的文件句柄。更麻烦的是它的依赖编译环节,像 pydantic-core、tokenizers 这类 Rust/Cython 扩展,在 Windows 上没有预编译 wheel 时经常当场开始编译,然后报一堆 MSVC 版本不匹配的错。我在 Windows 原生环境试过,连openclaw init都没撑过去。
所以想在 Windows 上跑起来,不是装个 exe 能解决的。你需要一个 Linux 环境,而 Windows 用户最体面的方案就是 WSL。
1.2 WSL、虚拟机、Docker 三种方案怎么选
我也考虑过另外两条路,最后都放弃了,这里把我的对比结论给出来:
| 方案 | 启动速度 | 资源占用 | 硬件直通 | 与 Windows 文件互访 | 适合场景 |
|---|---|---|---|---|---|
| WSL2 | 秒级 | 动态内存分配,较轻 | GPU 可直接用(CUDA) | 非常方便,但跨盘 IO 慢 | Windows 主力机跑 Linux 服务,首选 |
| Hyper-V/VMware 虚拟机 | 分钟级 | 固定内存,较重 | 需要额外配置 RDP/共享文件夹 | 通过共享目录,体验一般 | 需要完整桌面环境,或测试内核模块 |
| Docker Desktop | 秒级 | 取决于容器 | GPU 需单独配 nvidia-container-toolkit | 通过 volume 挂载 | 适合直接跑现成 OpenClaw 容器镜像,但不利于二次开发 |
最终选 WSL2 的核心原因有三个。第一,WSL2 是轻量级虚拟机,但启动只需要一秒,OpenClaw 作为常驻服务随时拉起不心疼。第二,WSL2 天然支持 NVIDIA CUDA,后面用 Ollama 跑本地模型可以直接调用 GPU 算力,不需要像虚拟机那样做一堆透传配置。第三,WSL2 与 Windows 共享 localhost 网络端口,Windows 侧的工具可以和 WSL 里的服务直接通信,这对 OpenClaw 的 Companion 工具来说太重要了。
1.3 最终架构长什么样
我最终搭起来的环境长这样:
- Windows 11,安装 WSL2,发行版选择 Ubuntu 22.04 LTS
- WSL 内部通过 Node.js 20 + Python 3.10 跑 OpenClaw 本体
- 模型接入有两个通道:本地 Ollama 跑开源模型,需要跨 Windows/WSL 访问时走 localhost 转发
- OpenClaw 以 systemd 服务方式常驻运行,开机自启,日志统一由 journalctl 管理
- Windows 侧安装 OpenClaw Companion 配套工具,负责剪贴板共享、系统通知、快捷唤醒
这套架构的好处是,OpenClaw 的所有核心逻辑都跑在 Linux 环境里,和官方文档保持一致;Windows 侧只做交互和展示,出问题也不会拖垮整个系统。
2. 初始化 WSL 之前,先把版本和资源配置想清楚
2.1 别急着升 WSL 3.0,也别用 WSL1
网上有 WSL 3.0 的讨论,听起来很诱人,但我实际看下来,WSL 3.0 还处在快速迭代期,周边工具链的兼容性没有完全跟上。我在升级后遇到过 Python 虚拟环境启动变慢、Docker Desktop 联动异常的问题,花了一晚上回滚。我的建议是:现阶段锁定 WSL2 的稳定版本即可,不要盲目追新。
如何确认当前 WSL 版本?在 PowerShell 里执行:
wsl --version如果输出的版本号低于 2.0.4,建议先运行 Windows Update 把系统补丁打全,再执行:
wsl --update另外要明确一点:一定要用 WSL2,不要用 WSL1。WSL1 是 API 翻译层,不是真虚拟机,OpenClaw 依赖的 systemd、inotify、完整的 Docker 网络栈在 WSL1 里都是残缺的。检查方法是在 PowerShell 执行:
wsl -l -v看到 VERSION 列是 2 就对了。如果是 1,用下面命令转换:
wsl --set-version Ubuntu-22.04 22.2 发行版选择:Ubuntu 22.04 LTS 比 24.04 更稳
WSL 里装什么发行版,看似随手一选,实际影响很大。我一开始装的是 Ubuntu 24.04,预装 Python 3.12,看着很新鲜,但接二连三踩坑:OpenClaw 的部分依赖底层用了 Python 3.10 时代编译的扩展,在 3.12 上只能现场重新编译,编译过程中又冒出各种系统库缺失的错误。后来我重新装了 Ubuntu 22.04 LTS,自带 Python 3.10,很多依赖直接命中预编译缓存,安装过程顺滑得多。
如果你还没有安装发行版,建议在 PowerShell 里直接指定版本安装:
wsl --install -d Ubuntu-22.04安装完成后进入 WSL,立刻做两件事:更新软件源并升级基础工具。
sudo apt update && sudo apt upgrade -y sudo apt install -y build-essential git curl wget unzipbuild-essential一定不能省,后面编译 Python 扩展和 Node 原生模块都需要整套 GCC 工具链。很多教程默认你已经装好了,但我遇到的情况是 90% 的编译失败都源于缺了build-essential。
2.3 .wslconfig 资源配置与发行版磁盘迁移
WSL2 默认内存占用是动态的,但 OpenClaw + Node + Python + Ollama 跑起来之后,内存很容易飙到 4GB 以上,默认配置下 Windows 会抱怨内存不足。我建了C:\Users\你的用户名\.wslconfig文件,手动控制资源上限:
[wsl2] memory=12GB processors=8 swap=8GB networkingMode=mirrored localhost=true解释一下参数:
memory=12GB:给 WSL 最大 12GB 内存,防止吃掉整个物理内存。如果你的机器只有 16GB 内存,建议设为8GB。processors=8:允许 WSL 使用 8 个逻辑核心,编译依赖和跑模型推理都能快一截。swap=8GB:WSL 的交换文件,在跑大模型或者长时间任务时不容易被 OOM 杀掉。networkingMode=mirrored:镜像网络模式,让 WSL 和 Windows 共享网络接口,这样 localhost 互访最省心。但注意,部分企业网络环境用了特殊网络过滤驱动时,mirrored 模式会导致 WSL 无法联网,遇到这种情况就把它改为默认的 NAT 模式。
修改.wslconfig后,必须让 WSL 完全重启才生效:
wsl --shutdown然后重新进入 WSL,用free -h验证内存上限是否生效。
还有一个非常容易忽略的问题:WSL 默认装在 C 盘,OpenClaw 的模型缓存、日志文件、依赖动辄几十 GB,C 盘分分钟爆掉。为了避免重装,建议在安装发行版时就指定位置。新版本 WSL 支持:
wsl --install -d Ubuntu-22.04 --location D:\WSL如果已经装好了,可以用迁移命令把发行版挪到 D 盘:
wsl --manage Ubuntu-22.04 --move D:\WSL\Ubuntu-22.04--manage --move这个参数需要 WSL 版本在 2.0.4 以上,不支持的话先执行wsl --update。迁移过程大概几分钟,完成后可以用wsl -l -v再次确认发行版状态正常。
3. OpenClaw 本体的安装过程:依赖、命令与目录规划
3.1 安装通用依赖链
进入 WSL 命令行后,开始安装 OpenClaw 的运行时依赖。核心依赖是 Node.js 和 Python。
Node.js 我强烈建议用 NodeSource 装 LTS 版本,而不是用 apt 自带的旧版:
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt install -y nodejs检查版本:
node -v npm -vPython 方面,Ubuntu 22.04 自带 Python 3.10,但还需要确保 pip 和 venv 可用:
sudo apt install -y python3-pip python3-venv python3-dev这里有个小细节:OpenClaw 的 Python 扩展会用到 systemd 的 Python 绑定,所以最好也装上:
sudo apt install -y libsystemd-dev pkg-config如果漏装了libsystemd-dev,后面加载某些服务扩展时会报cannot find -lsystemd的链接错误。
3.2 克隆源码编译,而不是 npm 全局安装
OpenClaw 有两种常见安装方式:npm 全局安装预编译包,或者从源码仓库克隆后手动构建。我第一次图省事用了 npm 全局安装,确实能跑起来,但有两个问题。第一,没法快速升级和查看源码,出问题连日志堆栈对应的代码位置都找不到;第二,OpenClaw 的 Skill 二次开发基本是围绕仓库目录展开的,全局安装模式下修改 Skill 要跑到全局 node_modules 里,权限和路径都很别扭。
所以我的建议是从源码构建。找一个你希望存放工程文件的目录,然后执行:
git clone https://github.com/openclaw/openclaw.git cd openclaw npm ci npm run buildnpm ci和npm install的区别是:npm ci严格按照 lock 文件安装,不会动依赖版本,构建环境更可复现。这一跑就会把所有的依赖和核心代码编出来,时间取决于网络状况,我这边大概需要五到十分钟。
构建完成后,把 OpenClaw 的命令链接到系统路径:
npm link然后执行初始化:
openclaw init初始化的过程中会询问项目目录、默认模型、消息平台接入方式等,全部按默认回车即可,后面都可以通过改配置文件来调整。初始化结束后,你会得到一个.openclaw配置目录,这是后续所有折腾的主战场。
3.3 openclaw init 之后,目录结构长什么样
初始化完成后,查看~/.openclaw目录,结构大致如下:
~/.openclaw/ ├── config/ │ └── openclaw.yml # 核心配置文件 ├── logs/ │ ├── openclaw.log # 运行日志 │ └── error.log # 错误日志 ├── skills/ # Skill 技能目录 ├── memory/ # 记忆存储 ├── keys/ │ └── credentials.json # 第三方凭证 └── sessions/ # 会话历史这个目录结构要记牢,因为后面 90% 的排错都是围绕这里展开的。config/openclaw.yml是主配置,logs是排错第一现场,skills用来管理自定义技能扩展。Skills 支持从本地目录导入,也支持从远程仓库拉取,具体命令在 GitHub 仓库的 README 里有文档,这里不展开。
4. 配置阶段最容易翻车的四个环节:模型、消息平台、端口和文件权限
4.1 API 接入还是 Ollama 本地算力
很多人问 OpenClaw 是不是只能通过 API 方式使用算力。不是,OpenClaw 支持本地模型后端。因为我经常处理敏感文本,不希望所有内容都发到云端,所以最终采用的是本地 Ollama + 云端 API 双轨方案:日常简单任务走本地模型,复杂任务临时切换到云端大模型。
两种方案的对比如下:
| 维度 | 云端 API | 本地 Ollama |
|---|---|---|
| 响应速度 | 依赖网络,通常 1-3 秒 | 显卡好时 0.5-2 秒 |
| 隐私性 | 数据出本机 | 完全本地 |
| 算力要求 | 无,按量付费 | 建议 16GB 显存以上 |
| 模型能力 | 可用顶级模型 | 取决于你拉取的模型 |
| 离线可用 | 不可用 | 完全离线可用 |
如果你选本地 Ollama,安装就一条命令:
curl -fsSL https://ollama.com/install.sh | sh然后拉取一个适合日常任务的中小参数模型,比如 Qwen2.5 系列,注意要以能塞进显存为前提:
ollama pull qwen2.5:14b安装完 Ollama 后,确认服务在 WSL 里监听 11434 端口:
ollama serve curl http://127.0.0.1:11434/api/tags返回 JSON 数组就说明可用。后面 OpenClaw 配置里的模型地址直接指向这个端口即可。
4.2 配置文件核心字段拆解
OpenClaw 的主配置位于~/.openclaw/config/openclaw.yml。我拿自己正在用的配置做个拆解:
agent: name: my-openclaw model: provider: ollama name: qwen2.5:14b temperature: 0.3 max_tokens: 8192 base_url: http://127.0.0.1:11434/v1 platforms: telegram: enabled: true bot_token: "你的Telegram Bot Token" discord: enabled: false skills: auto_load: true allow_remote: false memory: enabled: true max_entries: 500几个容易踩坑的字段:
base_url结尾不要漏掉/v1。Ollama 的 OpenAI 兼容接口挂在/v1路径下,漏掉这个路径会导致 404,而且 OpenClaw 报错时只会告诉你connection failed,定位起来非常痛苦。max_tokens不要设置成 0 或过小。某些后端会把 0 当作无限,而 OpenClaw 的默认值如果没配好,生成长文本会被截断。- 模型名一定要写 Ollama 里
ollama list查到的确切名字,很多朋友写成qwen2.5-q4_k_m.gguf这种文件名字段,注定匹配不上。
配置完之后用openclaw doctor检查配置是否正常,这个命令会帮你诊断配置文件的语法错误和网络连通性。
4.3 端口和 localhost 的互通规则
OpenClaw 的消息平台接入需要在本地监听端口,比如 Telegram Bot 长轮询、自定义 Webhook 回调等。这里最容易出问题的是 WSL2 的网络模型。
如果你用的是默认 NAT 模式,WSL2 启动的服务会自动被转发到 Windows 的 localhost 上。也就是说,WSL 里 OpenClaw 监听了127.0.0.1:8000,Windows 浏览器里直接访问http://127.0.0.1:8000就能通。但这有个前提:localhostForwarding没被关掉。
如果你像我一样已经在.wslconfig里开启了networkingMode=mirrored,那么 WSL 和 Windows 完全共享 localhost,互访没有障碍。但镜像模式有一个副作用:部分需要绑定固定源 IP 的软件会拿不到本机 IP,在 WSL 里执行curl ifconfig.me、ip addr时看到的网络形态都和 NAT 模式不同。如果只是日常使用,这个影响不大。
端口被占用的排查方法,我建议先在 Windows 侧执行:
netstat -ano | findstr :8000如果发现端口被别的进程占用,再执行:
taskkill /PID 进程号 /F在 WSL 里确认监听状态用:
ss -tlnp | grep 8000OpenClaw 启动后如果长时间连不上消息平台,大概率就是端口没监听或者被防火墙拦了。
4.4 永远不要把项目放在 /mnt/c 下
这是一条血的教训。很多人(包括我)习惯把工程代码放在D:\projects里,然后在 WSL 里通过/mnt/d/projects去访问。Windows 和 Linux 互访看起来爽,但跨文件系统的性能非常感人,而且有两个致命问题。
第一,符号链接(symlink)在 Windows NTFS 和 WSL 虚拟文件系统之间经常失效。Node.js 的npm ci在/mnt/c下常常会报symlink权限错误,解决起来非常麻烦。第二,inotify 文件监听在跨盘文件系统上行为异常,OpenClaw 的 Skill 自动重载功能会间歇性失效,日志里只会留下一堆无意义的EVENT OVERFLOW警告。
所以,OpenClaw 本体和所有依赖必须放在 WSL 的原生文件系统里,比如~/openclaw。Windows 侧需要共享文件时,再从 WSL 往 Windows 发,而不是反着来。
5. 把 OpenClaw 托管成常驻服务:systemd、开机启动与日志
5.1 开启 systemd 支持
OpenClaw 作为个人助理,不可能每次都用openclaw serve手动拉起来。我把它注册成了 systemd 服务,这样开机自启、崩溃自恢复、日志统一管理全都解决了。
老版本 WSL 默认不带 systemd,好在现在的 WSL2 已经支持了。开启方法:先退出 WSL,在 Windows 侧编辑C:\Users\你的用户名\.wslconfig(如果之前没建过就新建),加入:
[boot] systemd=true然后执行wsl --shutdown,重新进入 WSL,执行:
systemctl --version能输出版本号就说明 systemd 生效了。这一步如果没生效,可能是 WSL 版本太低,先执行wsl --update再试。
5.2 编写服务单元文件
我用 root 权限在/etc/systemd/system/openclaw.service创建了服务文件,内容如下:
[Unit] Description=OpenClaw Agent Service After=network-online.target Wants=network-online.target [Service] Type=simple User=你的WSL用户名 WorkingDirectory=/home/你的WSL用户名/openclaw ExecStart=/usr/bin/npm run serve Restart=on-failure RestartSec=10 Environment=NODE_ENV=production [Install] WantedBy=multi-user.target注意几个细节:
ExecStart需要写绝对路径,先用which npm确认 npm 的真实路径。写在WorkingDirectory之外的命令要能被 systemd 找到。User不要用 root。虽然 root 最简单,但 OpenClaw 产生的日志文件权限全是 root,后续你在普通用户下改配置、写 Skill 会遇到各种权限冲突。Restart=on-failure是必备项,OpenClaw 偶尔会因为上游 API 超时闪退,有这个配置会在 10 秒后自动拉起来。
写完服务文件后,依次执行:
sudo systemctl daemon-reload sudo systemctl enable openclaw sudo systemctl start openclaw查看运行状态:
sudo systemctl status openclaw如果状态显示active (running),就说明服务已经跑起来了。
5.3 "start the windows daemon from a non-elevated terminal" 的真相
安装 OpenClaw 的 Python 依赖时,我遇到过一条非常诡异的报错,完整文本是:
error: start the windows daemon from a non-elevated terminal; shared clients第一次看到这条消息时人直接懵了。查了一圈发现,这个报错来自 Poetry,是它在 Windows 上的服务进程管理模式。当你用管理员权限的 PowerShell 启动 Poetry 相关命令时,Poetry 的 Windows daemon 会拒绝从提权终端启动,因为共享客户端和服务端在同一会话下需要非提升权限。挺反直觉的,对吧?完整版安装指南里很少提到这一点。
解决办法倒是很简单:关掉管理员终端,用普通权限的用户终端重新执行 Poetry 命令,或者在 WSL 终端里执行,不要从 Windows 侧以管理员身份去触发。如果你确实需要在 PowerShell 里跑,记得用普通权限。
5.4 Docker Desktop 升级后 WSL 起不来的自救
OpenClaw 的一些隔离工具链依赖 Docker,所以我在 Windows 上装了 Docker Desktop。结果有次 Docker Desktop 自动升级之后,WSL 彻底起不来了,打开终端直接卡死在启动界面,连wsl -l -v都超时。
这是因为 Docker Desktop 自带的 WSL 集成组件升级后,和已有发行版的虚拟化平台配置产生了冲突。我当时没重装 WSL,用下面的三板斧解决了:
wsl --shutdown等十秒后重新启动 WSL。如果还是起不来,重置 Docker Desktop 的 WSL 集成设置,把 OpenClaw 对应的发行版取消勾选再重新勾选。最后实在不行,在管理员的 PowerShell 里执行:
netsh winsock reset然后重启电脑。这个操作会重置 Windows 网络栈,对 WSL 网络驱动异常特别有效,但代价是很多软件的网络连接需要重新建立。
6. 高频报错自查清单与一次真实排错案例
6.1 高频报错对照表
我把折腾过程中遇到的高频报错整理成一张表,遇到同样问题直接查:
| 报错现象 | 定位方向 | 解决方案 |
|---|---|---|
command not found: openclaw | 全局路径未生效 | 确认是否执行过npm link;重启终端或重开 WSL 会话 |
Cannot find module xxx | 依赖不完整 | 在项目目录执行npm ci重新安装依赖 |
Failed to connect to localhost:11434 | Ollama 未启动或地址错误 | 确认ollama serve正在运行,检查base_url是否带/v1 |
symlink EPERM operation not permitted | 跨盘文件系统权限问题 | 把项目迁到 WSL 原生目录,避免/mnt/c |
Memory limit exceeded | WSL 内存分配不足 | 调整.wslconfig的memory和swap,然后wsl --shutdown |
EACCES: permission denied | 文件权限问题 | 检查服务和日志文件 owner,用 chown 修正 |
Docker Desktop cannot connect to WSL | Docker 与 WSL 集成冲突 | 重置 Docker Desktop WSL 集成设置,必要时重装 |
event loop error或EVENT OVERFLOW | inotify 跨盘监听异常 | 将 Skill 目录移回 WSL 原生文件系统 |
6.2 真实排错案例:Windows 侧访问不到 OpenClaw 的消息平台端口
有一天 OpenClaw 服务状态正常,journalctl也没有报错,但 Windows 侧 Companion 工具始终提示连接不上消息平台。我花了半小时定位。
第一步,先确认 OpenClaw 确实在监听:
sudo ss -tlnp | grep openclaw输出显示进程监听在127.0.0.1:8000,没有异常。
第二步,在 WSL 里测试端口从外部访问:
curl http://127.0.0.1:8000/health响应正常。
第三步,在 Windows 的 PowerShell 里测试:
curl http://127.0.0.1:8000/health结果卡住,连接超时。
这说明监听虽然存在,但没有被转发到 Windows 侧。联想到之前动过.wslconfig网络模式,我判断问题出在网络配置。于是执行wsl --shutdown,然后重新进入 WSL,OpenClaw 服务启动后,Windows 侧再次访问就通了。
这个案例的教训是:如果你改过.wslconfig,特别是networkingMode和localhostForwarding,一定要记得重启 WSL 让配置完整加载,而不是指望热生效。
6.3 国内环境下的换源与提速
安装 OpenClaw 依赖时,如果你发现npm ci慢到令人发指,或者pip install卡在某个包上下载不完,可以考虑换源。我用的是三个源替换:
npm 全局源切换:
npm config set registry https://registry.npmmirror.compip 源切换到清华镜像:
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simpleapt 源替换为中科大镜像,这里需要编辑/etc/apt/sources.list,把默认地址批量替换成https://mirrors.ustc.edu.cn/ubuntu/,然后执行sudo apt update。
源切换之后再跑一次依赖安装,速度能快一个数量级,少很多无谓的等待。换源之后如果下载出现奇怪的校验和错误,先清缓存重试,比如 npm 执行npm cache clean --force,pip 执行pip cache purge。
最后说几句我的实际体会
一套流程跑通之后,最深的感触是:OpenClaw 在 WSL 里的稳定性,远超我最初的想象。前期所有折腾其实都集中在环境适配,一旦 systemd 托管跑起来,它就是一个可靠的常驻智能体,配合本地 Ollama 模型,基本可以做到全天候在线。
如果让我重新装一遍,我会在第一时间就确认三件事:WSL2 版本和资源配置、项目绝对不要放在/mnt/c、 Poetry 相关命令用普通终端跑。这三个坑占了全部排错时间的三分之二。
顺便分享一个小技巧:OpenClaw 的日志默认在~/.openclaw/logs/,但如果你用 systemd 托管,journalctl -u openclaw -f看日志更实时。我习惯开着这个命令观察服务状态,也方便随时把报错信息粘贴到群里问人。后续你如果打算在安卓上部署 OpenClaw,或者把它和 ROS2、Gazebo 那套机器人生态连起来,这套 WSL 环境的经验依然适用,底层跑通之后,剩下的就只是玩法问题了。