跳转至

Agent 平台部署

一、这页讲什么

一个人在本机终端里跑 Agent,关掉窗口任务就没了,换台机器接不上,别人也看不见。这页把 Agent 从「某人的本机会话」变成「部门里多人多台设备都能稳定用」的一层:组网连通、会话常驻、统一控制台、失败通知。

读完能做成:在一台常开机器上起控制面,把第二台设备接进来,关掉本地终端后从另一台机器接回同一个任务。

二、开始之前

项 内容
更新日期 2026-10-21
适用版本 Docker 27+;Tailscale 1.80+;tmux 3.4+
预计耗时 首台 2 小时,之后每加一台 20 分钟
风险级别 中。会新增常驻服务与开放端口,改动前先记下原状态
前置 一台常开机器(控制面)、若干被管理设备、组网已通

先定两件事再动手:设备清单(主机名、角色、负责人、是否常开),以及控制面绑哪个地址。后者只能绑组网地址或 127.0.0.1,不要直接对公网开。

三、动手做

3.1 先确认组网连通

控制面与被管理设备必须在同一个可互访的网段里。用组网工具把设备拉进同一张网,再从控制面 ping 每台设备。

$ tailscale status | head -3
<tailnet 地址>   server-a   linux   -    active; direct <公网地址>:41641
<tailnet 地址>   laptop-b   windows -    active; relay "tok"
$ ping -c 1 laptop-b
PING laptop-b (<tailnet 地址>): 56 data bytes
64 bytes from <tailnet 地址>: icmp_seq=0 ttl=64 time=12.4 ms

能从控制面 ping 通每台设备就算成。组网细节见 Tailscale 专题。

3.2 起控制面容器

控制面负责发现设备、转发指令、展示会话。用容器跑,数据卷单独挂出来,重建容器不丢配置。

$ docker run -d --name agent-console \
    -p 127.0.0.1:8080:8080 \
    -v /srv/agent-console/data:/data \
    --restart unless-stopped \
    <控制面镜像>
$ docker ps --filter name=agent-console
CONTAINER ID   IMAGE   STATUS          PORTS                      NAMES
a1b2c3d4e5f6   ...     Up 12 seconds   127.0.0.1:8080->8080/tcp   agent-console

看到状态 Up 且端口只绑在 127.0.0.1 就算成。绑 0.0.0.0 等于把控制台暴露到局域网,需要另做鉴权。

需要从别的机器访问时,用组网代理或反向代理转发,不要改容器端口绑定。代理写法见 反向代理与 HTTPS。

3.3 在被管理设备上装连接器

连接器主动外连控制面,设备不必开放入站端口。每台设备一个唯一标识,注册后控制面才能列出它。

$ <连接器> register --server http://<控制面地址>:8080 --name laptop-b
Registered connector: laptop-b (id 8f3c...)
$ <连接器> status
connected  server=http://<控制面地址>:8080  id=8f3c...

控制台设备列表里出现这台设备、状态为在线就算成。连接器要做成开机自启,否则重启即掉线。

3.4 把 Agent 放进常驻会话

约定一条:所有 Agent 都跑在常驻会话里,不跑在裸终端。用 tmux 起带名字的会话,分离后会话继续跑。

$ tmux new -s agent-laptop-b-build
# 在会话里启动 Agent,然后 Ctrl+B 再按 D 分离
$ tmux ls
agent-laptop-b-build: 1 windows (created Tue Oct 21 10:30:12 2026)
$ tmux attach -t agent-laptop-b-build

关掉本地终端重新 SSH 上去,tmux attach 能看到原现场就算成。

会话命名用「agent-设备-用途」,设备命名用「角色-编号」。名字里带设备与用途,半年后还看得懂是谁的任务。

3.5 接一个通知出口

长任务跑完要有人知道。推送服务或 IM 机器人留一个出口就够,多个出口会互相抢占,表现为「有时收到有时收不到」。

$ curl -s -X POST "$WEBHOOK" -d '{"text":"agent-laptop-b-build finished"}' -w '%{http_code}'
200

手机收到这条测试消息就算成。

四、做完怎么确认

检查项 期望结果
docker ps 控制面容器 Up,端口只绑 127.0.0.1
控制台设备列表 每台被管理设备在线
关掉本地终端再连 tmux attach 回到原会话,任务还在跑
从另一台机器打开控制台 能看到该设备的会话
手动发一条通知 手机收到

五、卡住了怎么排查

症状 多半是 怎么办
注册报「记录正忙」 上次注册没干净退出,锁没释放 找残留进程停掉再重试;反复点重试只会一直命中同一把锁
设备一直离线 连接器没起 / 组网不通 / 控制面地址写错 在设备上看连接器日志,先 curl 控制面确认可达
注册成功但重启后没了 连接器没做开机自启 做成 systemd 服务或计划任务
访问控制台报 Invalid Host header 绑了非本机地址但没声明公开地址 补访问控制与公开地址配置,仍不要开到公网
两台设备抢同一个标识 复制了同一份注册记录 每台设备单独注册,一机一个连接器实例
通知有时收到有时收不到 起了多个机器人 只留一个出口

连接器注册不上的根因通常是「上一次没退干净」。这类「首次启动自动迁移旧数据」的逻辑必须是幂等且可跳过的,否则迁移失败后重试永远命中同一把锁。

六、为什么这样能成

四层各管一件事,可以分开换:组网决定「通不通」,会话常驻决定「断线死不死」,控制台决定「在哪管」,通知决定「谁知道」。换掉一层不用动其它层,组网换错只是不通,控制台换错只是换界面。

Agent 跑在被管理设备的常驻会话里,控制台只是遥控器:控制面重启不杀任务,某台设备掉线只影响那一台。连接器主动外连,被管理设备不需要暴露入站端口,风险面比反向代理小。

七、边界与替代

  • 只有一台机器、一个人用:不需要控制面,组网 + tmux + 通知就够。
  • 有「元数据不能经过第三方」的要求:把组网换成自托管控制面,其余三层不动。
  • 不要把控制面直接开到公网:需要外部访问就放在组网内,或放在带鉴权的反向代理后面。
  • 不要用插件方式接控制面:Linux 上插件方式容易出现注册记录冲突,用独立连接器程序。
  • 一台设备只装一个连接器实例:两个实例会争同一份注册记录。

八、官方资料

控制面本身是自托管组件,版本与部署参数以内部部署记录为准(见内部台账)。以下几项由上游项目维护,规则以官方文档为准: