Claude Code 实战 09|远程与浏览器:让 Agent 伸手到别人的主机和网页里原创
# Claude Code 实战 09|远程与浏览器:让 Agent 伸手到别人的主机和网页里
前面几篇里,Agent 的手都停在本机:读本地文件、跑本地命令、调本地 CLI。但真实任务经常在"别处"——要排查一台只能内网 SSH 的 Windows 主机,要抓一个必须登录态才能看的网页。这篇讲两条把 Agent 的手伸出去的通道:SSH 后端让它在远端主机上跑命令,浏览器 CLI 让它操控一个已登录的 Chrome 去抓网页。两条通道都好用,但都有一批"环境不在你这边"带来的专属坑。
# 1. 场景:内置终端到不了的两个"别处"
Agent 的内置终端只在它自己的运行环境里生效。有两类任务天然在环境之外:
- 别人的主机:一台内网 Windows 小盘告警、一台远程 Linux 要看日志——Agent 得先"过去",才能查。
- 需要登录态的网页:一个必须登录才能看的后台、一个动态渲染的新闻列表——
curl拿不到,因为它既没有你的 Cookie,也不跑 JS。
这两类的共同点是:目标状态不在 Agent 的本地环境里。解法不是让 Agent 去"模拟",而是给它一条真实通道——SSH 连到那台机器、CDP/扩展接到那个真实浏览器。通道一旦接通,Agent 用的还是它熟悉的那套"跑命令、读输出",只不过命令落在了远端。
# 2. SSH 后端:让命令落在远端主机上
Claude Code(以及多数 Agent 框架)支持把终端后端从 local 切成 ssh。切过去之后,Agent 的每一条命令都在远程主机上执行。配置层面是一个 terminal.backend: ssh + 目标主机;使用层面有三条要立刻建立的认知:
- 先确认"我在哪、是谁、在哪个目录":连上一台陌生远端,第一件事是
hostname && whoami && pwd。工作目录的假设很容易错——本地约定的 workspace 路径在远端根本不存在,直接跑就是No such file or directory。稳妥做法是先用workdir="/"探明有效路径,再进具体目录。 - 先判断 shell 类型:SSH 到 Windows,默认进的是 PowerShell,不是 Bash。在里面
uname会报错,&&不是合法分隔符(PowerShell 用;,逻辑或用-or)。上来先认清 shell,能省掉一大批ParserError。 - 警惕跨会话/跨环境的连接串台:多套远端环境并存时,上一个环境的连接可能"漏"进下一个会话,导致命令落错主机。切换环境后,用
hostname复核一次落点,比事后查错误便宜得多。
# 3. 远程主机排查实战:Windows 健康检查三板斧
一个高频场景是被叫去看一台远程 Windows 主机的资源瓶颈。SSH 进去(PowerShell 环境)不用装任何 Agent,直接用 CIM/WMI 就能拿到结构化数据:
- 内存 / 启动时间:
Get-CimInstance Win32_OperatingSystem(看TotalVisibleMemorySize、FreePhysicalMemory); - 磁盘空间:
Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3"(Size/FreeSpace); - 资源大户:
Get-CimInstance Win32_Process | Sort-Object WorkingSetSize -Descending。
这里有两个必踩的陷阱,Agent 尤其容易在上面输出出错误结论:
- 单位陷阱:
Win32_LogicalDisk/Win32_Process返回的都是字节,不换算成 GB/MB 直接报给用户,数字大到没法读。必须在脚本里/1GB、/1MB转换。 - 指标歧义:
Win32_Process的KernelModeTime/UserModeTime是累计运行秒数,不是实时 CPU 负载。要实时负载得用Win32_Processor | Select LoadPercentage。把累计时间当成负载百分比报出去,就是一本正经的错。
真正做清理时(比如小盘告警),优先级也有定式:DISM 组件清理(/StartComponentCleanup /ResetBase)> Windows Update 缓存 > 升级残留目录($WinREAgent、$WINDOWS.~BT)> 浏览器缓存 > 安装包残留。还要小心 Junction 软链接(如 Documents and Settings 指向 Users)导致的空间重复计数——扫描时排除 Junction,否则统计翻倍。
# 4. 浏览器 CLI:操控一个"已登录"的真实 Chrome
抓需要登录态、需要跑 JS 的网页,正解是让 Agent 通过浏览器 CLI(CDP/扩展方式)接管一个真实的 Chrome,而不是用 curl。标准四步流水线:
doctor确认连接:检查 Daemon 状态与扩展是否挂上(有固定端口,如19825);open <url>打开页面:拿到一个 page ID,作为后续操作的上下文句柄;wait time 3等渲染:动态内容要给它几秒,否则 extract 到的是空壳;extract提取内容:优先--selector "main"缩小 DOM 范围,拿 Markdown;页面很长时用返回的next_start_char分页,避免单次输出被截断。
在远程 Windows 上启动这个 Chrome 有个绕不过的坎:Session 0 隔离。SSH 会话跑在 Session 0,直接启动的 Chrome 在用户桌面不可见,Daemon 也就挂不上。标准解法是用一次性计划任务以 Interactive 模式在用户桌面拉起 Chrome,用完 Unregister 清掉:
New-ScheduledTaskPrincipal -UserId "<user>" -LogonType Interactive -RunLevel Highest
Register-ScheduledTask -TaskName "OpenChrome" -Action $action -Trigger $trigger -Principal $principal -Force
# 用完即焚
Unregister-ScheduledTask -TaskName "OpenChrome" -Confirm:$false
2
3
4
# 5. 踩坑:环境不在你这边,坑就藏在环境里
这两条通道的坑,几乎全都来自"运行环境不是本地":
- 坑一·Node PATH 缺失:浏览器 CLI 多是 npm 全局包,依赖 Node。远程 Shell(Git Bash/PowerShell)的 PATH 里常常没有
node,报node: not found。判据先分清是"工具没装"还是"node 不在 PATH"——后者远比前者常见,显式指定 Node 绝对路径即可。 - 坑二·选择器落空与参数幻觉:
extract --selector命中不了复杂站点的 DOM 就返回空;Agent 还容易幻觉出不存在的参数(比如给extract传--goal,报unknown option)。解药是先--help核对真实参数、先看页面结构再定选择器,命不中就全量提取交给 LLM 后处理。 - 坑三·权限 scope 不足:Token 鉴权的架构里,本地 CLI 设备的 scope 常常不够(
browser操作要更高权限),报device token scope mismatch。更阴的是自授权死循环——approve本身也要 admin 权限。解药是从已有管理权限的另一端(Control UI / 已配对的管理端)去批准,CLI 自己批不了自己。 - 坑四·全量抓取撑爆上下文:把远端拉回来的原始数据(长网页、大批日志)整个塞进 Prompt,瞬间触发上下文上限、静默失败。永远不要全量注入——在查询/提取层就限流(Top-N、分页、聚合),让回传的数据量可控。
# 6. 可复用要点
- 两条外伸通道:SSH 后端让命令落在远端主机,浏览器 CLI 让 Agent 接管一个已登录的真实 Chrome——目标状态不在本地时,接真实通道而不是让 Agent 模拟。
- 连上远端先定位:
hostname && whoami && pwd,先探明落点和有效路径(workdir="/"起步),先认清 shell 类型(Windows 默认 PowerShell,&&不合法)。 - 远程 Windows 排查:CIM/WMI 三板斧拿结构化数据;注意字节→GB 换算、累计时间 ≠ CPU 负载、Junction 重复计数。
- 浏览器四步流水线:
doctor → open → wait → extract;远程启动 Chrome 要用计划任务绕过 Session 0 隔离。 - 坑都在环境里:Node 不在 PATH、选择器落空/参数幻觉、Token scope 不足(自授权死循环)、全量抓取撑爆上下文——记住"运行环境不是本地",一半的坑就能提前避开。
# 7. Agent 可直接解析的元数据块
{
"_meta": {
"doc_version": "2026-07-28",
"article_id": "claude-code-09-remote-browser",
"profile_context": "any",
"estimated_setup_time": "30min"
},
"quick_start": {
"step_1": "切 terminal.backend: ssh 让命令落在远端;连上先 hostname && whoami && pwd 定位,workdir=\"/\" 探路,认清 shell 类型(Windows=PowerShell)",
"step_2": "抓登录态/动态网页用浏览器 CLI 接管真实 Chrome:doctor → open → wait → extract,用 --selector 缩范围、next_start_char 分页",
"step_3": "远程 Windows 启动 GUI Chrome 用一次性计划任务(Interactive 模式)绕过 Session 0 隔离,用完 Unregister"
},
"safety_rules": [
"永远不要把远端拉回的原始数据(长网页/大批日志)全量注入 Prompt,在查询/提取层限流(Top-N/分页/聚合)",
"切换远端环境后用 hostname 复核落点,防止上一个环境的 SSH 连接串台导致命令落错主机",
"远程 Windows 数值单位是字节,报给用户前必须换算 GB/MB;KernelModeTime/UserModeTime 是累计秒数不是 CPU 负载",
"Token 鉴权下 CLI 无法自授权(approve 也需 admin),browser scope 不足时从已有管理权限的另一端批准"
],
"verification": {
"check_1": "浏览器 CLI 报 node: not found 时先分清是工具没装还是 node 不在远程 Shell PATH(后者常见,指定绝对路径)",
"check_2": "extract 返回空时先 --help 核对参数(勿幻觉 --goal 等)、先看页面结构再定 selector,命不中则全量提取交 LLM",
"check_3": "远程路径 No such file or directory 时用 workdir=\"/\" 或 hostname/whoami/pwd 探明有效路径,勿套用本地 workspace 假设"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
AI Agent 使用指南:
- 当用户说"帮我看看那台远程 Windows/Linux 主机" → 按
quick_start.step_1切 SSH 后端,先定位再动手,认清 shell 类型。 - 当用户说"抓一下这个要登录/动态渲染的网页" → 按
quick_start.step_2用浏览器 CLI 接管真实 Chrome,别用 curl。 - 当用户说"远程启动浏览器起不来/看不见" → 按
quick_start.step_3,SSH 会话在 Session 0,用计划任务以 Interactive 模式在用户桌面拉起。 - 当用户说"抓回来的数据太大/工作流报 context 溢出" → 按
safety_rules,在查询/提取层限流,永不全量注入。 - 当用户说"browser 命令报 scope mismatch/权限不足" → 按
safety_rules,CLI 不能自授权,从已有管理权限的另一端批准设备。
上一篇:Claude Code 实战 08|子 Agent 与编排:让一个 Agent 变成一支小队 下一篇:Claude Code 实战 10|端到端:用 Agent 搭一条博客自动化发布流水线
- 02
- MySQL 性能压测:Sysbench 1.0 实战 原创07-29
- 03
- MySQL Router 实现读写分离 原创07-29