前提:OpenClaw Gateway 部署在 Linux 服务器上,Home 节点跑在 Windows WSL2 Ubuntu 里。
背景
我的 OpenClaw 架构:
- Gateway:Linux 服务器(192.168.31.113)
- Home 节点:Windows 11 + WSL2 Ubuntu(桌面在 F:\Desktop)
- Work 节点:公司电脑 WSL2
需要通过 OpenClaw 远程操作 Home WSL 节点上的文件,读写 Windows 分区的项目代码。
踩坑1:exec 看不到 Windows 盘符
现象
# WSL 终端里一切正常
likefr@DESKTOP-4F1J92R:~$ ls /mnt/f/Desktop/
01-项目代码 02-压缩包 ...
# 但 OpenClaw exec 命令看不到
$ ls /mnt/f/Desktop/
ls: cannot access '/mnt/f/Desktop/': No such file or directory原因
OpenClaw 的 exec 命令跑在节点进程的 mount namespace 里。WSL 的 Windows 盘符(C/D/E/F 盘)是通过 drvfs(9p 文件系统)动态挂载的,如果挂载发生在节点进程启动之后,exec 就看不到。
验证方法
# 在 exec 里检查
mount | grep drvfs # 空!
cat /proc/self/mountinfo | grep 9p # 空!
ls /mnt/f/ # 空
# 在 WSL 终端里检查
mount | grep drvfs # 能看到所有盘符解决方案
方案A:/etc/fstab 预挂载(推荐)
在 WSL 的 /etc/fstab 里预先声明所有盘符,这样 WSL 启动时就挂好:
sudo tee -a /etc/fstab << 'EOF'
C: /mnt/c drvfs defaults 0 0
D: /mnt/d drvfs defaults 0 0
E: /mnt/e drvfs defaults 0 0
F: /mnt/f drvfs defaults 0 0
G: /mnt/g drvfs defaults 0 0
H: /mnt/h drvfs defaults 0 0
EOF然后 wsl --shutdown 重启 WSL。
方案B:system service + ExecStartPre 挂载
把 OpenClaw 节点改成 system 级 service(root 权限),在启动前挂载:
# /etc/systemd/system/openclaw-node.service
[Service]
ExecStartPre=/bin/bash -c 'until [ -d /mnt/c/Users ]; do sleep 1; done'
ExecStartPre=/bin/bash -c 'mkdir -p /mnt/f && mount -t drvfs F: /mnt/f 2>/dev/null; true'
ExecStartPre=/bin/bash -c 'mkdir -p /mnt/d && mount -t drvfs D: /mnt/d 2>/dev/null; true'
ExecStart=/usr/bin/openclaw node run --host YOUR_HOST --port 443 --tls --display-name "Home"⚠️ 注意:普通用户的 user service 没有权限 mount,必须用 system service(root)。踩坑2:WSL cat > 写 Windows 文件为空
现象
# exec 里 cat > 写文件,看似成功
echo "hello" > /mnt/f/Desktop/test.txt
# 但 Windows 侧看到文件 size=0!
# PowerShell 确认
PS> (Get-Item F:\Desktop\test.txt).Length
0原因
WSL 的 sh/bash 通过 cat > 写到 /mnt/f/ 或 /mnt/c/ 的文件,Windows 侧看到 size=0。这是 9p 文件系统的缓存问题,在某些 mount namespace 配置下会出现。
验证
# 用 PowerShell 单引号 here-string 可以写(不解析 ${})
# 但需要 .ps1 文件方式调用解决方案
不要用 exec 的 cat/echo 写 Windows 文件! 用 OpenClaw 的 file_write 工具。
踩坑3:exec 路由到了 Gateway 而不是 WSL 节点
现象
所有 exec 命令都在 Gateway(Linux 服务器)上执行,而不是 WSL 节点:
hostname
# 输出:multi-server(这是 Gateway 服务器,不是 WSL)原因
OpenClaw 的 agent 配置里 tools.exec.node 绑定了节点 ID。如果绑错或者节点不在线,exec 会 fallback 到 Gateway 本机。
// openclaw.json
{
"agents": {
"list": [
{
"id": "devops",
"tools": {
"exec": {
"node": "正确的节点ID"
}
}
}
]
}
}解决方案
- 确认节点 ID:在 Control UI 的 Nodes 页面查看
- 绑定正确节点:配置
agents.list[].tools.exec.node为目标节点的完整 ID - 确保节点在线:如果节点离线,exec 会 fallback 到 Gateway
- exec 命令加 host=node:
host="node", node="Home"确保路由到节点
最终正确姿势
✅ 读文件:file_fetch
file_fetch(node="Home", path="/mnt/f/Desktop/project/config.json")走节点插件的文件通道,不受 mount namespace 限制。
✅ 写文件:file_write
file_write(node="Home", path="/mnt/f/Desktop/project/newfile.java", contentBase64="...")同样走节点插件的文件通道,Windows 侧能看到完整内容。
✅ 路径格式
必须用:/mnt/f/Desktop/...
不能用:F:\Desktop\... 或 F:/Desktop/...✅ 执行命令(需要 fstab 或 service 预挂载)
# 确保节点能看到盘符后
exec(host="node", node="Home", command="ls /mnt/f/Desktop/")systemd service 完整配置
user service(普通用户,推荐)
# ~/.config/systemd/user/openclaw-node.service
[Unit]
Description=OpenClaw Node
After=network-online.target
Wants=network-online.target
[Service]
ExecStartPre=/bin/bash -c 'until [ -d /mnt/c/Users ]; do sleep 1; done'
ExecStart=/usr/bin/openclaw node run --host YOUR_HOST --port 443 --tls --display-name "Home"
Environment=OPENCLAW_GATEWAY_TOKEN=YOUR_TOKEN
Restart=always
RestartSec=5
[Install]
WantedBy=default.target配合 fstab 预挂载
# /etc/fstab 追加
C: /mnt/c drvfs defaults 0 0
D: /mnt/d drvfs defaults 0 0
E: /mnt/e drvfs defaults 0 0
F: /mnt/f drvfs defaults 0 0
G: /mnt/g drvfs defaults 0 0
H: /mnt/h drvfs defaults 0 0总结
| 操作 | 工具 | 说明 |
|---|---|---|
| 读写 Windows 文件 | file_write / file_fetch | 走插件通道,不受 namespace 限制 |
| 路径格式 | /mnt/x/... | 不能用 X:\... |
| exec 看盘符 | fstab 预挂载 | 确保 WSL 启动时就挂好 |
| exec 路由 | host="node" + 正确 node ID | 避免 fallback 到 Gateway |
| WSL cat 写文件 | ❌ 别用 | Windows 侧看到 size=0 |
一句话总结:读写 Windows 文件一律用file_write/file_fetch,路径格式/mnt/x/...
本文由 Summer(OpenClaw AI 助手)协助整理,基于 2026-05-22 的真实踩坑过程。