在一套多主机自动化环境中,AI 代理需要远程控制一台 Linux 桌面设备上的专用浏览器。这个浏览器使用独立用户数据目录启动,同时开启本机回环地址上的远程调试接口,再通过 SSH 隧道供另一台控制主机访问。

这套流程过去一直可以正常工作,但桌面环境从 X11 切换到 Wayland 后,代理突然无法打开可见的浏览器窗口,并判断当前系统“没有图形显示环境”。

经过手动测试和流程修正,最终确认问题并不在浏览器,也不在 Wayland,而在于代理获取图形会话环境的方法仍然停留在旧的 X11 逻辑。

一、原有工作方式

整个浏览器控制流程大致分为四部分:

  1. 在桌面主机上启动一个专用浏览器实例。
  2. 使用独立的浏览器用户数据目录,避免干扰日常浏览器。
  3. 浏览器仅在本机回环地址上开放远程调试接口。
  4. 控制主机通过 SSH 本地端口转发连接该调试接口。

正常情况下,代理不仅可以读取网页内容,还可以操作可见浏览器窗口,例如:

  • 打开指定网页;
  • 点击页面中的链接;
  • 模拟鼠标滚动;
  • 在页面中停留;
  • 返回上一页;
  • 连续浏览多篇内容;
  • 将最终页面保持在屏幕上。

这种方式与普通无头浏览不同。操作过程会真实显示在桌面上,坐在屏幕前的人可以同步观看。

二、出现的问题

桌面环境切换到 Wayland 后,代理尝试启动浏览器时发现:

DISPLAY 为空
WAYLAND_DISPLAY 为空

随后代理直接得出结论:

当前没有可用的图形显示环境,无法打开可见浏览器窗口。

表面上看,这个判断似乎合理,但实际上检查的是代理当前所在的 SSH shell,而不是桌面主机中正在运行的真实图形会话。

SSH 登录产生的非图形 shell 没有继承桌面会话变量,是完全正常的现象。即使桌面上正在运行完整的 KDE Wayland 会话,SSH 终端中的相关变量仍然可能为空。

因此,不能根据 SSH shell 中的环境变量判断远程设备是否存在图形会话。

三、手动测试

为了区分浏览器故障和代理逻辑故障,首先在桌面主机本地终端中进行了测试。

本地图形终端可以正常读取到以下类型的环境信息:

XDG_SESSION_TYPE=wayland
WAYLAND_DISPLAY=<Wayland 显示名称>
DISPLAY=<XWayland 显示编号>
XDG_RUNTIME_DIR=<用户运行时目录>

随后使用以下参数启动专用浏览器:

browser \
  --ozone-platform=wayland \
  --user-data-dir="<专用浏览器数据目录>" \
  --remote-debugging-address="<本机回环地址>" \
  --remote-debugging-port="<远程调试端口>" \
  "https://www.google.com/"

测试进行了两次,两次都顺利打开了可见浏览器窗口,并正常进入目标网页。

这说明:

  • Wayland 图形会话正常;
  • 浏览器支持 Wayland;
  • 专用用户数据目录正常;
  • 远程调试模式正常;
  • 目标网页可以正常访问;
  • 故障仅存在于代理的远程启动逻辑中。

四、真正的原因

旧流程主要针对 X11 环境设计,通常从 X11 窗口管理器进程获取环境变量。

切换到 Wayland 后,真实桌面会话由 Wayland 合成器负责。代理仍然查找旧的 X11 会话进程,或者只检查自身 SSH shell 的变量,因此无法获得正确的图形环境。

正确的方法应当是:

  1. 登录桌面主机;
  2. 找到当前用户正在运行的 Wayland 合成器进程;
  3. 找不到时再使用桌面外壳进程作为回退;
  4. 从该进程的 /proc/<PID>/environ 中读取环境;
  5. 将需要的变量导入当前 shell;
  6. 再从这个 shell 中启动浏览器。

需要读取的变量主要包括:

DISPLAY
WAYLAND_DISPLAY
XDG_RUNTIME_DIR
XDG_SESSION_TYPE
DBUS_SESSION_BUS_ADDRESS
XAUTHORITY

其中,XAUTHORITY 在部分环境中可能不存在,不应将其作为 Wayland 启动的强制条件。

五、修正后的启动逻辑

修正后的流程不再检查控制主机或 SSH shell 自身的显示变量,而是主动读取桌面主机的真实图形会话。

逻辑可以概括为:

# 优先查找 Wayland 合成器
GUI_PID="$(查找当前用户的 Wayland 会话进程)"

# 找不到时回退到桌面外壳进程
if [ -z "$GUI_PID" ]; then
    GUI_PID="$(查找当前用户的桌面外壳进程)"
fi

# 从真实图形进程读取环境
读取 "/proc/${GUI_PID}/environ"

# 仅导出启动浏览器所需的图形和会话变量
导出 DISPLAY
导出 WAYLAND_DISPLAY
导出 XDG_RUNTIME_DIR
导出 XDG_SESSION_TYPE
导出 DBUS_SESSION_BUS_ADDRESS
存在时导出 XAUTHORITY

# 使用 Wayland 模式启动专用浏览器
browser \
  --ozone-platform=wayland \
  --user-data-dir="<专用浏览器数据目录>" \
  --remote-debugging-address="<本机回环地址>" \
  --remote-debugging-port="<远程调试端口>"

专用浏览器的识别依据应当是独立用户数据目录,而不是浏览器程序名称。这样可以避免关闭或干扰日常使用的浏览器窗口。

六、不能只看启动器进程是否退出

浏览器启动时还存在一个容易误判的现象。

有时启动命令返回后,shell 会显示启动器进程已经结束,但浏览器窗口实际上已经正常打开。这通常是因为启动请求被交给了已有的浏览器主进程,启动器完成转交后自行退出。

因此,不能仅根据后台任务是否显示为 Done 判断浏览器启动失败。

更可靠的验收依据包括:

  • 桌面上是否出现专用浏览器窗口;
  • 是否存在使用专用数据目录的浏览器进程;
  • 远程调试接口是否可以访问;
  • 调试接口返回内容中是否包含 WebSocket 调试地址;
  • 控制主机的 SSH 隧道是否可以正常连接。

七、完整验收

浏览器启动逻辑更新后,再次让代理执行可见浏览任务。

代理成功完成了以下操作:

  1. 打开专用浏览器;
  2. 进入新闻网站主页;
  3. 随机选择三篇新闻;
  4. 通过可见的鼠标点击进入文章;
  5. 从文章顶部开始缓慢向下滚动;
  6. 每屏停留足够时间;
  7. 让屏幕前的人能够同步阅读;
  8. 读完后返回新闻主页;
  9. 继续打开下一篇文章;
  10. 完成三篇后停留在最后一篇文章页面;
  11. 全程未影响日常浏览器实例。

这次测试说明,修复后的流程不仅可以远程打开浏览器,还可以完成具有真实观看节奏的可见浏览操作。

八、这次解决了哪些问题

这次排查最终解决了以下问题:

1. 修复 Wayland 下无法远程打开可见浏览器的问题

浏览器本身并没有故障,真正需要更新的是代理的图形会话发现逻辑。

2. 纠正 SSH 环境变量为空的错误判断

SSH shell 中没有 DISPLAYWAYLAND_DISPLAY,不代表目标设备没有图形桌面。

3. 将图形环境来源从旧 X11 进程改为 Wayland 会话进程

优先从 Wayland 合成器读取环境,桌面外壳进程仅作为回退。

4. 明确 Wayland 浏览器启动参数

启动专用浏览器时显式指定 Wayland 图形后端,避免依赖浏览器自动判断。

5. 保留专用浏览器与日常浏览器之间的隔离

通过独立用户数据目录识别专用实例,不关闭、不修改日常浏览器。

6. 建立了更可靠的启动验收标准

不再只看启动器进程是否退出,而是综合检查窗口、进程、调试接口和 SSH 隧道。

7. 验证了可见浏览和同步阅读能力

代理可以缓慢滚动并留出阅读时间,而不是快速跳过页面或仅在后台提取文字。

九、经验总结

远程启动 Linux 图形程序时,最重要的不是当前 shell 中有什么环境变量,而是目标桌面会话实际使用了什么环境。

从 X11 切换到 Wayland 后,以下原则尤其重要:

  • 不要假设 SSH shell 会继承桌面环境;
  • 不要根据空的显示变量直接判定没有图形会话;
  • 应从真实桌面进程读取环境;
  • Wayland 与 X11 的会话进程不同;
  • 浏览器启动结果应通过多个信号共同验证;
  • 专用自动化浏览器必须与日常浏览器隔离;
  • 可见浏览任务应明确滚动速度和停留时间。

这次故障本质上不是浏览器兼容性问题,而是自动化流程没有跟随桌面会话类型的变化同步更新。

当图形环境发现逻辑修正后,原有的远程调试、SSH 隧道和浏览器自动化流程仍然可以继续使用。

Leave a Reply

Your email address will not be published. Required fields are marked *