1. OpenClaw 浏览器自动化在 systemd 下 DISPLAY 丢失的真实场景OpenClaw 的浏览器自动化能力本质上是让一个带图形界面的浏览器在后台被程序驱动。它适合做需要登录态、需要渲染、需要点击交互的网页任务比如内容平台发布、后台系统操作、带验证码的流程复现。问题在于这类任务一旦交给 systemd 托管浏览器就很容易起不来报错往往指向 X11 显示服务器连不上。我遇到的现象很典型手动在终端里执行openclaw browser start一切正常浏览器窗口能弹出来但同样的命令被 systemd 服务拉起时进程存在、日志却在刷cannot open display或者Missing X server or $DISPLAY。这不是 OpenClaw 本身坏了而是 systemd 服务进程没有继承到 DISPLAY 和 XAUTHORITY 这两个关键环境变量。要理解这件事得先分清两条线。第一条是「谁在跑」OpenClaw Gateway 可能是用户级服务systemctl --user也可能是系统级服务systemctl两者的环境加载路径完全不同。第二条是「图形会话在哪」VNC 或本地 X 会话通常跑在:1或:0对应/tmp/.X11-unix/X1这样的 socket 文件。服务进程如果不知道 DISPLAY 指向哪个显示号浏览器就没有落脚点。这篇排查清单按三条线展开服务单元配置、会话环境注入、进程继承验证。每一步都给可复制的命令和配置片段最后把服务侧 endpoint 改到 TaoToken 后逐项复测确保浏览器自动化和模型调用两条链路都通。2. TaoToken 前置准备把服务侧 endpoint 与 Key 配好在动 systemd 之前先把 OpenClaw 要用的模型侧配置准备好。浏览器自动化只是执行层真正驱动决策的模型请求需要走一个稳定的 endpoint。TaoToken 在这里扮演的是统一接入层你拿到一个 Base URL 和一个 API Key就能在 OpenClaw 的配置里替换掉原来的模型地址不用改业务代码。先到控制台创建 Key。打开 https://taotoken.net/api-keys 登录后新建一个 API Key复制出来。这个 Key 只显示一次建议直接写进环境变量文件而不是硬编码在服务单元里。Base URL 用https://taotoken.net/api注意这个地址不带任何查询参数。模型 ID 按你实际要用的填比如claude-sonnet-4-20250514或gpt-4o这类。OpenClaw 的配置通常放在用户目录下的配置文件中具体路径取决于你的安装方式。如果你用的是 Claude Code 风格的配置可以打开 https://taotoken.net/doc 对照文档里的字段名。一个常见的做法是把模型配置写进~/.openclaw/config.json或项目根目录的.env。下面是一个可复制的 JSON 片段路径按你实际安装位置调整{ model: { provider: openai-compatible, base_url: https://taotoken.net/api, api_key: sk-你的Key, model_id: claude-sonnet-4-20250514 }, browser: { headless: false, display: :1 } }如果你更习惯用环境变量可以在服务单元里通过EnvironmentFile引入# /root/.config/openclaw/env OPENCLAW_BASE_URLhttps://taotoken.net/api OPENCLAW_API_KEYsk-你的Key OPENCLAW_MODEL_IDclaude-sonnet-4-20250514这里有个容易踩的坑Key 里如果包含特殊字符写进 systemd 的Environment时要用引号包住否则会被截断。用EnvironmentFile更省心文件权限设成600避免被其他用户读到。配置好之后先别急着重启服务用一条 curl 验证模型侧通不通curl -s https://taotoken.net/api/v1/models \ -H Authorization: Bearer sk-你的Key | head -c 300返回模型列表就说明 Key 和 Base URL 没问题。这一步单独验证能把「模型连不上」和「浏览器起不来」两类问题分开后面排障时不会互相干扰。3. 可复制的 systemd 单元与 DISPLAY 注入配置现在进入核心部分。先确认 OpenClaw Gateway 到底是用户级还是系统级服务这决定了配置文件放哪。systemctl --user status openclaw-gateway 2/dev/null | head -5 systemctl status openclaw-gateway 2/dev/null | head -5如果第一条有输出且显示Loaded: /root/.config/systemd/user/openclaw-gateway.service那就是用户级服务。用户级服务的配置目录在~/.config/systemd/user/系统级在/etc/systemd/system/。两者不要混用改错地方重启也不会生效。确认显示号。VNC 通常跑在:1本地 X 会话可能是:0ls -la /tmp/.X11-unix/看到X1就说明显示号是:1。同时确认 XAUTHORITY 文件位置root 用户一般是/root/.Xauthorityls -la /root/.Xauthority接下来创建 drop-in 配置。drop-in 的好处是不动原始单元文件升级时不会被覆盖。用户级服务执行mkdir -p /root/.config/systemd/user/openclaw-gateway.service.d然后写入/root/.config/systemd/user/openclaw-gateway.service.d/display.conf[Service] EnvironmentDISPLAY:1 EnvironmentXAUTHORITY/root/.Xauthority EnvironmentFile-/root/.config/openclaw/env注意EnvironmentFile前面的-表示文件不存在时不报错适合可选配置。如果你用的是系统级服务路径换成/etc/systemd/system/openclaw-gateway.service.d/display.conf但系统级服务默认不继承用户会话的 X11 权限还需要额外处理 xhost 或 XAUTHORITY 权限所以能用户级就用户级。重新加载并重启systemctl --user daemon-reload systemctl --user restart openclaw-gateway如果你同时改了模型配置重启后服务会重新读取env文件里的 Base URL 和 Key。这里给一个完整的用户级单元示例方便对照字段[Unit] DescriptionOpenClaw Gateway Afternetwork.target [Service] Typesimple ExecStart/usr/bin/openclaw gateway Restarton-failure EnvironmentDISPLAY:1 EnvironmentXAUTHORITY/root/.Xauthority EnvironmentFile-/root/.config/openclaw/env [Install] WantedBydefault.targetWantedBydefault.target是用户级服务的写法系统级对应multi-user.target。写错会导致systemctl --user enable失败。还有一个隐藏问题VNC 的 xstartup 如果没有加载 nvmVNC 终端里的 node 版本可能和系统不一致。这会影响 OpenClaw 依赖的 Node 运行时。编辑/root/.vnc/xstartup加上 nvm 初始化#!/bin/bash unset SESSION_MANAGER unset DBUS_SESSION_BUS_ADDRESS export DISPLAY:1 export NVM_DIR$HOME/.nvm [ -s $NVM_DIR/nvm.sh ] \. $NVM_DIR/nvm.sh if [ -x /usr/bin/dbus-launch ]; then eval $(dbus-launch --sh-syntax --exit-with-session) fi exec startxfce4改完重启 VNCvncserver -kill :1 vncserver :1 -geometry 1280x800 -depth 24这样 VNC 会话里的 Node 版本就和系统一致了OpenClaw 在图形会话里手动测试时不会因为版本错位出现奇怪报错。4. 验证请求与成功结果从进程环境到浏览器启动配置写完必须验证不能只看服务状态是 active 就认为好了。按下面顺序逐项确认。第一步确认服务进程真的拿到了 DISPLAY。先拿 PIDsystemctl --user show openclaw-gateway -p MainPID假设输出MainPID12345然后读进程环境cat /proc/12345/environ | tr \0 \n | grep -E DISPLAY|XAUTHORITY期望看到DISPLAY:1 XAUTHORITY/root/.Xauthority如果这里为空说明 drop-in 没生效回到上一步检查路径和daemon-reload。第二步验证 X11 连通性。用xdpyinfo或xset测试DISPLAY:1 XAUTHORITY/root/.Xauthority xdpyinfo | head -5能打印出屏幕分辨率、深度等信息就说明 X 服务器可达。如果报unable to open display检查 VNC 是否在跑、/tmp/.X11-unix/X1是否存在、XAUTHORITY 权限是否可读。第三步验证模型侧请求。用服务同样的环境变量发一条请求source /root/.config/openclaw/env curl -s https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $OPENCLAW_API_KEY \ -H Content-Type: application/json \ -d {model:$OPENCLAW_MODEL_ID,messages:[{role:user,content:ping}]} \ | head -c 300返回带choices的 JSON 就说明模型链路通。这一步和浏览器无关单独验证能排除 endpoint 配置错误。第四步启动浏览器自动化openclaw browser start openclaw browser open https://example.com如果浏览器正常启动并打开页面说明 DISPLAY 注入成功。此时再看服务日志journalctl --user -u openclaw-gateway -n 50 --no-pager日志里不应该再有cannot open display或Missing X server。如果还有重点看报错发生在哪个阶段是浏览器二进制启动失败还是页面加载超时。前者是 X11 问题后者可能是网络或模型决策问题。一个完整的成功链路应该是systemd 服务启动 → 进程环境含 DISPLAY → 浏览器进程继承 DISPLAY → 模型请求走 TaoToken 返回 → 自动化任务执行。任何一环断了日志都会指向具体位置。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth排障时最怕报错信息模糊。下面按真实报错逐条对照。401 Unauthorized。模型请求返回 401通常是 Key 没读到或写错。检查EnvironmentFile路径是否正确、文件权限是否可读、Key 是否有多余空格。用systemctl --user show openclaw-gateway -p Environment看服务实际加载了哪些变量。如果 Key 写在Environment里且含特殊字符改用EnvironmentFile。local proxy failed。这个报错一般出现在 OpenClaw 尝试通过本地代理转发请求时。检查配置里是否残留了旧的代理地址把 Base URL 统一改成https://taotoken.net/api。同时确认没有设置HTTP_PROXY之类的环境变量指向不存在的本地端口。用env | grep -i proxy排查。reading choices 报错。这通常意味着模型返回的 JSON 结构不符合预期常见原因是 Base URL 少了/v1或多了斜杠。TaoToken 的 API 地址是https://taotoken.net/api具体路径按文档拼接。用 curl 直接请求一次看返回体里有没有choices字段。如果返回的是 HTML 错误页说明地址写错了。OAuth 相关报错。如果你用的是 Claude Code 或 Codex 风格的认证OAuth token 过期会报认证失败。这类场景建议改用 API Key 方式在 https://taotoken.net/api-keys 重新生成一个写进env文件。OAuth 和 API Key 不要混用混用会导致认证头冲突。DISPLAY 设置了但浏览器仍起不来。检查 XAUTHORITY 权限。ls -la /root/.Xauthority应该是600且属主是运行服务的用户。如果服务以其他用户运行需要把 XAUTHORITY 复制过去或调整权限。另外确认 VNC 的-depth参数某些浏览器需要 24 位色深。服务重启后配置丢失。drop-in 文件如果放在错误目录daemon-reload不会加载。用户级服务必须在~/.config/systemd/user/下系统级在/etc/systemd/system/下。用systemctl --user cat openclaw-gateway查看实际生效的配置。Node 版本不一致。VNC 终端里node -v和系统不一致说明 xstartup 没加载 nvm。按第 3 节的 xstartup 片段修改重启 VNC 后验证。OpenClaw 依赖的 Node 版本如果低于要求会在启动时报语法错误。排查时养成一个习惯每改一处配置只重启对应服务然后立刻验证。不要一次改多个地方否则出问题不知道是哪一步引入的。6. 把服务侧 endpoint 改到 TaoToken 后的复测清单配置改完后按这个清单逐项复测确保浏览器自动化和模型调用都稳定。先确认服务状态和进程环境systemctl --user status openclaw-gateway --no-pager systemctl --user show openclaw-gateway -p MainPID cat /proc/$(systemctl --user show openclaw-gateway -p MainPID --value)/environ | tr \0 \n | grep -E DISPLAY|OPENCLAW再验证 X11 和模型两条链路DISPLAY:1 XAUTHORITY/root/.Xauthority xdpyinfo | head -3 source /root/.config/openclaw/env curl -s https://taotoken.net/api/v1/models -H Authorization: Bearer $OPENCLAW_API_KEY | head -c 200最后跑一次完整的浏览器自动化任务观察日志openclaw browser start openclaw browser open https://example.com journalctl --user -u openclaw-gateway -n 30 --no-pager如果日志干净、浏览器正常打开、模型请求返回正常说明整条链路通了。后续如果要做长期编码或 Agent 任务可以在 https://taotoken.net/coding-plan 看套餐配置需要调试模型对话效果用 https://taotoken.net/models 直接测试接入文档在 https://taotoken.net/doc 对照字段。Key 管理统一在 https://taotoken.net/api-keys 。一个实用技巧把复测命令写成一个脚本每次改配置后跑一遍比手动敲命令快得多。脚本里用set -e任何一步失败就停避免带着问题往下走。