把 OpenClaw 装进 WSL 之后,我一开始没觉得开机自启动是件值得专门写一篇的事。Windows 的任务计划程序里加一句 wsl 命令,听起来三行就能搞定。真正动手才发现,WSL 里跑着的是一个跟常规 Linux 服务不太一样的生态:发行版不是开机就自动挂载的虚拟机,进程生命周期受控于 Windows 会话和 WSL 自身的 init,环境变量和用户 HOME 在非交互启动时也会给你整出各种幺蛾子。这篇文章把我实测下来的三条启动路线和完整配置都列出来,适合已经能手动跑起 OpenClaw、但希望在 Windows 重启后自动把它拉起来的用户。你能得到一份可复制的启动脚本、Windows 侧的任务计划注册方法,以及几类最不容易定位的失败原因。
1. 先搞明白:WSL 里的程序生命周期,到底谁说了算
很多人卡在“开机启动 WSL 里的程序”这步,根本原因是把 WSL 当成了 VirtualBox 或 VMware 里的那台虚拟机。虚拟机只要设置为开机自启,里面的 guest OS 会完成整套启动流程,systemd 把服务带起来,MySQL、Redis 各种守护进程按依赖顺序跑步入场。但 WSL 不是这么工作的。
1.1 Windows 登录,并不等于某个 WSL 发行版会跟着启动
默认情况下,Windows 登录后不会自动拉起任何 WSL 发行版。WSL 更像一套“按需启动”的机制:你第一次在终端里敲 wsl 或者 wsl -d Ubuntu,对应的发行版才会被实例化,WSL 2 的轻量虚拟机才开始工作。所以你即使把 Linux 服务配成了开机自启,只要没有东西去触发 Windows 启动这个发行版,服务依然不会出现。
这就意味着,实现 WSL 里 OpenClaw 开机启动,你至少要在 Windows 侧放一个“牵引动作”,让 WSL 开机后被叫醒。这个牵引动作可以是一个计划任务,也可以是一次显式的 wsl.exe 调用。
1.2 你以为的任务启动,和真正的无人值守启动,差了一整套环境
我在第一次尝试时,直接在任务计划里写了:
text复制wsl.exe -d Ubuntu -- openclaw serve
结果任务计划程序显示“运行成功”,OpenClaw 却毫无反应。查了半天才意识到,WSL 通过这种非交互方式执行命令时,并不会加载你登录终端时那套 bash 环境。用户 HOME、PATH、/etc/profile.d 里导出的变量,全都没按你预期的来。更麻烦的是,OpenClaw 的工作区、模型配置、工具审批文件,一般都会放在 ~/.openclaw 目录下,如果 HOME 指向的不是你平时使用的用户目录,它在启动的时候根本找不到配置。
所以真正可靠的做法不是“一条 wsl 命令直达”,而是写一个能自包含环境变量的包装脚本,由计划任务去调用这个脚本。脚本内部负责找可执行文件、设置 HOME、准备日志目录、做幂等检查,然后把 OpenClaw 以后台方式拉起来。
1.3 为什么要用 nohup 和 setsid 这类“离终端”手段
另一个常见的现象是:计划任务里直接执行启动命令,当时进程确实起来了,但没过几十秒又没了。这是因为从 Windows 侧拉起的 wsl 进程,往往挂在一个临时控制台上,等任务计划程序认为 wsl.exe 执行完了,控制台关闭,终端信号传递到 Linux 进程组,把 OpenClaw 一起带走了。
解决办法是在启动脚本里给 OpenClaw 换一个完全独立的会话,让它的父进程变成 WSL 里的 init,而不是临时控制台。最常见的写法就是 setsid 配合 nohup,把标准输出和错误重定向到日志文件,让服务彻底“脱离终端”。这一步不是可有可无,而是整个自启动方案能不能稳定的关键。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 三条自启路线怎么选:任务计划、wsl.conf、systemd
我知道你在网上搜“wsl openclaw 开机启动”时,看到过各种方案,比如改 .bashrc、写 /etc/rc.local、用 Windows 启动文件夹放 .vbs。这些方法不是不能用,而是各自有前提条件和坑。下面把主流方案放在一起对比。
2.1 方案横向对比
| 方案 | 触发时机 | 优点 | 坑点 |
|---|---|---|---|
| Windows 任务计划程序 + wsl.exe 调用启动脚本 | Windows 登录时或开机时 | 触发时机明确,通用性强,适合所有 WSL 版本 | 需要处理非交互环境问题,可能闪黑窗口 |
WSL /etc/wsl.conf 的 [boot] command |
发行版被启动时 | 适合做 WSL 内部的环境初始化,配置简单 | 发行版不启动就不执行;仍需 Windows 侧先拉起发行版 |
| WSL 启用 systemd + systemd service | WSL 发行版启动后 | 可享受 systemctl 管理、自动重启、服务状态查询 |
需要对 systemd 有一定了解,Version 较老的 WSL 不支持 |
第一行是最通用、最容易被理解的主路线,也是我在生产环境里用得最多的。第二行适合作为“每次 WSL 启动后都想跑一下的初始化动作”,但如果你完全不在 Windows 侧触发 WSL,boot.command 依然不会在 Windows 登录后自动执行,它只能负责“当发行版启动后”这个后续动作。第三行是进阶玩法,适合希望把 OpenClaw 当成一个正规 Linux 服务来维护的用户,后面专门用一节来展开。
2.2 我建议的组合
如果你的目标只是“Windows 重启后,OpenClaw 能自动待命”,那最优解是:Windows 任务计划程序来触发,WSL 内部脚本做环境装配,OpenClaw 以独立会话方式常驻。这个组合最稳定,不依赖 WSL 新特性,也不要求你精通 systemd。
如果你已经习惯用 systemctl status 看服务状态,而且 WSL 版本支持 systemd,那可以在主路线上叠加 systemd:Windows 任务计划负责叫醒 WSL,systemd 负责常驻和崩溃重启。这样兼顾了 Windows 侧的开机触发和 Linux 侧的进程管理,后面第 6 节会给出具体做法。
3. 先写一个能脱离终端的 OpenClaw 自启包装脚本
不管最后用任务计划还是 systemd,第一步都是一样的:写一个可靠的启动脚本。这个脚本的作用不是简单执行 openclaw serve,而是要在无人值守的环境里,把 OpenClaw 需要的一切准备好。
3.1 写脚本前,先给 OpenClaw 做一次“体检”
在配置自启动之前,建议你先打开 WSL,手动跑一次平时正常启动 OpenClaw 的命令,确认几件事:
- OpenClaw 的可执行文件到底装在哪个路径,
command -v openclaw输出什么; - 启动时工作目录在哪里,工作区路径是否是
~/.openclaw/workspace; - 启动命令究竟是不是
openclaw serve,如果你平时用的是交互式命令,要先确认是否有适合后台运行的子命令; - 首次启动时是否会生成
exec-approvals.json这类审批文件,这个文件属于哪个用户。
这些信息直接决定脚本里 HOME、BIN、启动参数怎么写。尤其是安装用户,如果 OpenClaw 是用 root 用户配置的,那么 /root/.openclaw 下的审批文件和模型配置就只有 root 能找到。很多自启动失败并不是命令错了,而是脚本用普通用户去执行,结果连 /root/.openclaw 都进不去。
3.2 开始写脚本
我建议把脚本放到 /usr/local/bin/start-openclaw,这样所有用户都能执行,也方便 Windows 侧调用。先创建日志目录:
bash复制sudo mkdir -p /var/log/openclaw
sudo touch /var/log/openclaw/boot.log
然后创建脚本文件:
bash复制sudo vim /usr/local/bin/start-openclaw
脚本内容如下:
bash复制#!/usr/bin/env bash
# OpenClaw 自启动包装脚本
# 适用于 WSL 无人值守启动,已经过 Ubuntu 22.04/24.04 测试
OPENCLAW_USER="root"
OPENCLAW_HOME="/root"
OPENCLAW_LOG_DIR="/var/log/openclaw"
OPENCLAW_LOG_FILE="${OPENCLAW_LOG_DIR}/boot.log"
PID_FILE="/var/run/openclaw.pid"
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') $*" >> "$OPENCLAW_LOG_FILE"
}
# 先创建日志目录
[ -d "$OPENCLAW_LOG_DIR" ] || mkdir -p "$OPENCLAW_LOG_DIR"
# 非交互环境下不会加载 bashrc,需要手动引入环境变量
[ -f /etc/profile ] && . /etc/profile 2>/dev/null || true
# 查找 openclaw 可执行文件
BIN=""
for candidate in "$OPENCLAW_HOME/.local/bin/openclaw" \
"$OPENCLAW_HOME/.openclaw/bin/openclaw" \
"/usr/local/bin/openclaw" \
"/usr/bin/openclaw"; do
if [ -x "$candidate" ]; then
BIN="$candidate"
break
fi
done
if [ -z "$BIN" ]; then
BIN="$(command -v openclaw 2>/dev/null || true)"
fi
if [ -z "$BIN" ]; then
log "ERROR: openclaw binary not found, please check installation path"
exit 1
fi
log "using openclaw binary: $BIN"
# 幂等检查:如果已经有一个 openclaw 在运行,就不再重复拉起
if [ -f "$PID_FILE" ]; then
old_pid="$(cat "$PID_FILE" 2>/dev/null || true)"
if [ -n "$old_pid" ] && kill -0 "$old_pid" 2>/dev/null; then
log "openclaw already running with pid=$old_pid, skip"
exit 0
fi
fi
# 设置用户环境,进入 HOME 目录
export HOME="$OPENCLAW_HOME"
cd "$OPENCLAW_HOME"
# 关键点:setsid + nohup,让进程脱离当前控制台会话
setsid nohup "$BIN" serve >> "$OPENCLAW_LOG_FILE" 2>&1 &
new_pid=$!
echo "$new_pid" > "$PID_FILE"
log "openclaw started with pid=$new_pid"
exit 0
脚本里有几个细节值得单独解释一下。
/etc/profile 的引入是为了把非交互 shell 需要的 PATH 补全。很多通过官方脚本安装的 OpenClaw 会把可执行文件放到 /usr/local/bin 或用户目录下的隐藏目录,如果脚本找不到,日志里就会明确记录 openclaw binary not found,你可以在 for candidate 列表里补上实际路径。
幂等检查很关键。因为 Windows 登录后,用户可能还会手动打开终端再跑一次 OpenClaw,如果任务计划和手动操作同时触发,就会出现端口占用或重复实例的问题。有了 PID 文件检查,第二次执行会直接退出。
3.3 验证脚本
给脚本加执行权限:
bash复制sudo chmod +x /usr/local/bin/start-openclaw
先手动在 WSL 里执行一次:
bash复制sudo /usr/local/bin/start-openclaw
然后查看启动日志:
bash复制tail -f /var/log/openclaw/boot.log
再检查进程:
bash复制ps aux | grep openclaw
如果看到 OpenClaw 进程还在,说明脚本本身没问题。接着测试从 Windows 侧调用:
powershell复制wsl.exe -d Ubuntu -u root -- /usr/local/bin/start-openclaw
注意把 Ubuntu 替换成你实际的发行版名称,可以用 wsl -l -v 查看。如果这一步能成功,说明计划任务的主干已经通了。
4. 在 Windows 任务计划程序里挂上自动拉起入口
脚本就绪后,下一步是让 Windows 在登录时自动执行那条 wsl.exe 命令。Windows 侧的工具是“任务计划程序”,比启动文件夹更可靠,支持配置触发条件、延迟时间和运行权限。
4.1 用 GUI 创建任务
按 Win + R,输入 taskschd.msc 打开任务计划程序。
在右侧操作栏里点击“创建任务”,不是“创建基本任务”,因为后者选项较少。按下表配置:
| 配置项 | 推荐值 |
|---|---|
| 名称 | OpenClaw-Boot |
| 安全选项 | 勾选“使用最高权限运行” |
| 触发器 | “登录时”,延迟 30 秒 |
| 操作 | 启动程序:wsl.exe |
| 参数 | -d Ubuntu -u root -- /usr/local/bin/start-openclaw |
| 起始于 | 留空即可 |
延迟 30 秒是为了等网络和 WSL 环境更稳定。如果你的 WSL 发行版较多,或者网卡初始化慢,可以适当调高到 60 秒,但不建议超过 2 分钟,否则服务起来得太晚,已经失去了“开机自启”的意义。
注意,在“条件”选项卡里,把“只有在计算机使用交流电源时才启动”这一项取消勾选。否则笔记本如果没插电源,任务不会执行。在“设置”选项卡里,我一般会勾选“如果任务失败,按以下频率重新启动”,间隔设为 5 分钟,重试最多 3 次,这样偶尔启动失败后还能自己补救。
4.2 让 wsl.exe 启动时不闪黑窗口
直接使用 wsl.exe 作为任务操作时,登录瞬间可能会闪过一个黑色控制台窗口。虽然通常只持续半秒到一秒,但如果你在意这个问题,可以用一个 VBScript 中转,以隐藏模式启动。
在 Windows 侧创建 C:\scripts\openclaw-boot.vbs:
vbs复制Set ws = CreateObject("WScript.Shell")
ws.Run "wsl.exe -d Ubuntu -u root -- /usr/local/bin/start-openclaw", 0, False
Set ws = Nothing
然后把任务计划里的“操作”改成启动程序 wscript.exe,参数填:
text复制C:\scripts\openclaw-boot.vbs
VBScript 的第二个参数 0 表示隐藏窗口,第三个参数 False 表示不等待命令执行完成。这样任务计划程序会立刻返回,OpenClaw 的启动过程全部在 WSL 内部和日志文件中进行,Windows 桌面不会出现任何窗口闪烁。
4.3 命令行注册方式(可选)
如果你更习惯命令行,也可以用 schtasks 创建任务。以管理员身份打开 PowerShell:
powershell复制schtasks /Create /TN "OpenClaw-Boot" /SC ONLOGON /DELAY 0000:30 /RL HIGHEST /TR "wsl.exe -d Ubuntu -u root -- /usr/local/bin/start-openclaw"
创建后可以手动触发一次:
powershell复制schtasks /Run /TN "OpenClaw-Boot"
查询任务上一次运行结果:
powershell复制schtasks /Query /TN "OpenClaw-Boot" /V /FO LIST
不过 schtasks 对 GUI 里的“条件”和“设置”控制力弱一些,如果前面 GUI 配置已经成功,命令行方式了解一下就好。
5. 实测五类失败:为什么任务“跑了”但 OpenClaw 没起来
按上面的配置走完,大部分环境已经能正常工作。但如果你遇到了“任务计划显示运行成功,OpenClaw 就是没起来”的情况,不要急着怀疑方案,先按下面的排查链路走一遍。
5.1 wsl 命令指向了错误的发行版
如果你机器上装过多个 WSL 发行版,wsl.exe -d Ubuntu 这里的 Ubuntu 必须和 OpenClaw 实际所在的发行版一致。有时候从网上复制命令,里面写的是 Ubuntu-22.04,你的发行版是 Ubuntu,路径对不上自然启动失败。
先在 Windows 终端里确认:
powershell复制wsl -l -v
输出里有一个 NAME 列,把那一列的名字原样填进 -d 参数,不要自己脑补大小写。还有一种情况是发行版名字里带空格,比如 Ubuntu-22.04,这时 -d 参数要用英文双引号包起来,例如 "Ubuntu-22.04"。
5.2 openclaw 命令在非交互环境下找不到
我在排查时发现,很多用户手动敲 openclaw 能启动,是因为 .bashrc 或 .profile 里加了类似:
bash复制export PATH="$HOME/.openclaw/bin:$PATH"
可计划任务调用的 wsl.exe 是非交互 shell,.bashrc 根本不会被加载。脚本里虽然 source 了 /etc/profile,但如果你把 PATH 写在了用户级 .bashrc 里,还是读不到。
解决办法有两个:一是把 export PATH 加到 /etc/profile.d/ 下的某个 .sh 文件里,让所有非交互登录 shell 都能读到;二是直接在启动脚本的 for candidate 列表里写上 openclaw 的绝对路径。我更推荐第二种,因为它把依赖限定在了一个文件里,以后排查时只需要看一个脚本。
5.3 任务启动后进程又被 SIGHUP 带走
症状是任务计划里显示执行成功,日志里也写了 openclaw started,但过几分钟再看,进程没了。这个问题在第一次配置时最容易遇到,原因是启动方式没有脱离控制台。
如果你绕过了包装脚本,直接在任务计划里写:
text复制wsl.exe -d Ubuntu -u root -- openclaw serve
那就没有 setsid 和 nohup 的保护。wsl.exe 的命令执行完,Windows 侧认为任务已经结束,控制台关闭时产生挂断信号,OpenClaw 作为子进程被一起带走。
解决办法就是沿用第 3 节的脚本,让 setsid nohup 把 OpenClaw 放到独立会话里。如果脚本已经用了,进程依然消失,再检查 PID 文件是否写入成功,以及脚本中是否因为 set -e 在某一步提前退出了。
5.4 exec-approvals 旧文件让首次启动卡住
OpenClaw 这类智能体会有工具执行审批机制,需要人工确认某些命令能否执行。历史版本生成的审批文件格式如果比较旧,启动日志中可能出现类似:
text复制legacy exec approvals exist at /root/.openclaw/exec-approvals.json. run ...
这一行提示并不一定是致命错误,但它意味着自动启动前,OpenClaw 可能需要完成一次审批数据的迁移或重新确认。自启动场景下没有交互终端,这类需要人确认的操作会卡住服务。
最稳妥的做法是在配置自启动之前,先用交互方式手动启动一次 OpenClaw,按照提示处理掉旧的审批文件。如果提示明确要求跑某条命令,就在终端里执行;如果只是提醒文件存在,可以先把该文件备份到其他位置,让新版本重新生成。总之,不要让无人值守的启动流程去处理需要人工决策的审批迁移。
5.5 计划任务显示上次运行结果 0x1
任务计划程序里,上次运行结果如果显示 0x1,说明进程退出码是 1,也就是脚本执行失败。这时不要盯着 Windows 侧找原因,直接进 WSL 看 OpenClaw 自己的启动日志:
bash复制cat /var/log/openclaw/boot.log
日志里会写明是找不到可执行文件,还是启动命令报错,又或者是端口已经被占用。这类问题基本都在脚本可执行路径和权限上。
如果日志是空的,就先在 WSL 里手动跑一次脚本,把标准错误输出看到:
bash复制bash -x /usr/local/bin/start-openclaw
bash -x 会把脚本每一步执行过程打出来,看到哪一步异常,问题基本就定位了。
6. 进阶:开 systemd,用服务单元管理 OpenClaw
如果你和我一样,喜欢用 systemctl status 查看服务状态,希望服务崩溃后能自动重启,那可以把 OpenClaw 交给 WSL 里的 systemd 管理。这样 Windows 任务计划只负责叫醒 WSL,OpenClaw 是否存活、要不要拉起,全部交给 Linux 侧的守护进程。
6.1 在 WSL 里启用 systemd
新版 WSL 支持 systemd,需要修改 /etc/wsl.conf:
ini复制[boot]
systemd=true
然后在 Windows PowerShell 里执行:
powershell复制wsl --shutdown
重启 WSL 后验证:
bash复制systemctl --version
systemctl is-system-running
如果能看到 systemd 版本号并且 is-system-running 返回的不是 offline,说明 systemd 已经正常工作。
6.2 写一个 OpenClaw 的 systemd service
启用 systemd 后,创建服务单元文件 /etc/systemd/system/openclaw.service:
ini复制[Unit]
Description=OpenClaw Agent Service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=root
Environment="HOME=/root"
WorkingDirectory=/root
ExecStart=/usr/local/bin/start-openclaw
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
这里没有直接在 ExecStart 里写 openclaw serve,而是继续调用前面写的包装脚本。这样可以保留脚本里的环境变量加载和幂等检查逻辑。如果以后需要调整启动参数,改脚本就行,不用重新 daemon-reload。
然后执行:
bash复制systemctl daemon-reload
systemctl enable openclaw
systemctl start openclaw
查看状态:
bash复制systemctl status openclaw
用 systemd 管理的好处是,如果 OpenClaw 因为外部 API 抖动或某个依赖服务异常而崩溃,systemd 会在 10 秒后自动尝试重启,比 Windows 侧的任务计划重试机制更精细。
6.3 systemd 方案仍要保留 Windows 侧的牵引任务
需要特别提醒一句:即使启用了 systemd,服务也只在 WSL 发行版启动后才会被拉起。而 Windows 登录时默认并不会启动 WSL 发行版,所以第 4 节的 Windows 任务计划依然要保留,只是它的作用变成了“先启动 WSL 这个空壳”,再让 systemd 接管后续。
任务计划里的操作可以简化为只触发一个 true 命令:
text复制wsl.exe -d Ubuntu -u root -- /bin/true
这个动作执行完,WSL 发行版启动,systemd 进入流程,openclaw.service 会跟着起来。Windows 侧任务计划负责“开机牵引”,Linux 侧 systemd 负责“服务守护”,两边分工明确。
如果把第 4 节和第 6 节组合起来,你在 Windows 登录后 30 秒左右,OpenClaw 就已经通过 systemd 正常驻留在 WSL 里了。平时排查问题也简单得多:systemctl status openclaw 看状态,journalctl -u openclaw -f 看日志,不需要再猜 Windows 侧有没有把进程拉起来。
我个人在实际使用中偏向“Windows 任务计划 + systemd”这套组合,因为 OpenClaw 这种工具型智能体最怕的不是启动慢,而是运行中某一个环节崩了没人管。有了 systemd 的自动重启兜底,哪怕凌晨某个外部服务抖动导致 OpenClaw 进程异常退出,它也能在十几秒内自己恢复,不需要你第二天早上再手动敲一遍启动命令。
