AI SSH 运维 Agent · 网络设备接入能力
目 录
一、为什么需要它
二、核心设计:两条通道,权责分离
三、功能详解
3.1 统一设备清单,跨设备无感切换
3.2 懂 VRP 方言,不做「Linux 式误用」
3.3 报错是「读」出来的,不是「看退出码」看出来的
3.4 配置安全的三道闸门
3.5 强制「先读后写、写后回读」闭环
四、实战案例:一次完整的「检测 → 变更 → 验证」
目标一:配置 SW1 的接口地址池,可用地址 100~250
目标二:补充 DNS = 各网段网关 + 8.8.8.8
目标三:R1 补默认路由
五、程序主动告诉你的「坏消息」
六、变更台账与边界
七、小结
一、为什么需要它
网工日常的痛点很集中:设备在机房、只能 Telnet、命令方言各有一套。查一台交换机的 DHCP 池要背display ip pool interface Vlanif10,改一条路由要记得从用户视图一步步system-view → interface → quit → return。设备一多,「逐台登录、逐条敲、手工记账」就是纯粹的体力活,而风险恰恰藏在体力活里——打错一个字,一条shutdown或者一次save覆盖,代价是断网。
这套程序要解决的核心问题不是「让 AI 敲命令」,而是:在保留人工决策权的前提下,把可标准化的读与写拆开,让「看」变得零风险,让「改」变得可审计、可回滚。
二、核心设计:两条通道,权责分离
程序把网络设备的交互严格切成两个入口,对应两种不同的信任级别:
通道 | 工具 | 允许的操作 | 风险等级 |
只读巡检 | net_exec(host, command, timeout) | 仅 display / ping / tracert 白名单 | 零风险,可随意执行 |
配置变更 | net_config(host, commands[]) | 进入系统视图逐条下发 | 自动分级管控 |
这个「读写分离」不是形式主义,它带来三个实际好处:
- 巡检可以放开手做。排查问题时需要连续下发十几条 display,只读通道让这些操作完全无副作用,不需要你逐条确认。
- 变更天然留下「施工记录」。所有写操作都要经过 net_config,每条命令独立返回执行结果,天然形成一份变更清单,便于事后复盘。
- 误操作的物理闸门。即使模型判断失误想发一条 reboot,也过不了 net_config 的检查。
两条通道还配有「双向防误用」引导:把net_exec指向一台 Linux 服务器时,程序不会硬跑 Telnet,而是提示改走 SSH 命令通道;反过来,在 VRP 设备上直接发配置类命令,也会被引导到net_config,从入口上杜绝「用错通道」。同一个工具在错误的对象上不会沉默地失败,而是被纠正到正确的用法上。
三、功能详解
3.1 统一设备清单,跨设备无感切换
网络设备与服务器统一登记在同一份清单(config/hosts.yml)中,用逻辑名直接寻址:
AR1: 127.0.0.1:2000(华为路由器,免密直进)
SW1: 127.0.0.1:2001(华为交换机,免密直进)
调用时只需指定名字——net_exec("SW1", "display vlan"),无需关心它是 Telnet 还是 SSH、端口是多少。设备条目只需要四个字段:device_type: huawei_vrp加上地址、端口、备注,免密直进的模拟器设备用户名和密码全部留空即可。
除了手写配置文件,Web 界面的「添加受管主机」表单也内置了设备类型选择——选「华为 VRP(Telnet)」,用户名密码留空就能把一台免密模拟器设备纳入清单,与 CLI 共用同一份配置。
切换到网络设备时,程序会自动执行一次「入场体检」:采集display version与display ip interface brief的基线信息注入 AI 的上下文——设备型号、版本、接口 IP 概览在动手前就已就位,AI 不用盲目摸索。
更进一步,run_command_on_hosts支持一条命令在多台设备上并行执行,适合批量巡检;并且对网络设备同样前置只读检查——非白名单命令在任何一台 VRP 设备上都会被拦下,批量通道不会成为绕过闸门的后门。需要逐台执行不同命令时,再退回单机模式。同名设备的连接自动复用,反复下发命令不会反复重建 Telnet 会话。
3.2 懂 VRP 方言,不做「Linux 式误用」
这是很多通用 Agent 栽跟头的地方。程序内置了 VRP 方言约束(提示词层面的速查表,覆盖十类高频差异):
- 知道 VRP 的过滤语法与 Linux 不同——用| include / | exclude / | section,而不是 grep / awk。例如一条display current-configuration | include ip route-static就能精准捞出 R1 的全部静态路由。
- 知道system-view / return / quit由程序托管。写配置时只管写「业务命令」,不用手动切视图——net_config 自动进系统视图、自动返回用户视图。但视图内部的跳转仍由命令本身控制,所以下面这种写法是合法的:
["interface Vlanif10", "dhcp server dns-list 192.168.10.254 8.8.8.8",
"interface Vlanif20", "dhcp server dns-list 192.168.20.254 8.8.8.8"]
一组逻辑完整的命令在一个事务内下发,跨接口视图一气呵成,中间不用 quit。
- 知道 VRP 分页会截断长输出——连接建立后程序自动下发screen-length 0 temporary关闭分页,长配置一次读全,不会停在「---- More ----」。
- 知道 ping 是逐包打印的(约 2 秒/包),必须用-c 3控制包数并给足超时,否则会一直挂着。
3.3 报错是「读」出来的,不是「看退出码」看出来的
VRP 没有独立错误流、也没有可靠退出码。程序对此的处理原则是:一切以回显文本为准,并教会模型识别典型错误:
Error: Unrecognized command found at '^' position.
^
^ 精确指向语法出错的位置
程序内置了错误回显特征判定(Error / Unrecognized command / Incomplete command / Wrong parameter /at '^' position/ Too many / Ambiguous),命中即在结果中标注失败。遇到这类报错,正确姿势是根据 ^ 位置修正语法后重试,而不是原样重发——重发一万次也是同样的错。
3.4 配置安全的三道闸门
程序对写入命令做分级管控,这是整套设计里最有价值的部分:
级别 | 典型命令 | 行为 |
普通 | 接口 IP、VLAN、路由、DHCP | 直接执行,逐条返回结果 |
高危 | reboot、save、shutdown | 暂停,请求用户人工确认(CLI 终端 / Web 弹窗) |
毁灭性 | format、reset saved-configuration、factory-configuration、undo startup | 直接拒绝,不给执行机会,连确认弹窗都不会出现 |
同时,「写入运行配置」与「持久化到启动配置」被刻意拆成两步:net_config只改运行配置,save必须单独下发且必经人工确认——确认后程序还会自动应答设备侧的 [Y/N] 交互,全程无需手动干预。这条设计非常关键——它意味着任何配置变更在重启前都是「可撤销」的:拔掉重来即可回到原状。每次下发完成,程序都会在结果里附上提示「配置已写入运行配置;持久化需向用户确认后单独执行 save」,把重启决策权完整地留给你。
3.5 强制「先读后写、写后回读」闭环
程序把一条运维铁律固化成了行为规范:任何变更前先 display 确认现状,下发后再回读验证生效。
下面是一次标准示范。补 DNS 之前,先读两个地址池的现状:
DNS-server0 : - <- 确认原本为空
Gateway-0 : 192.168.10.254
下发后再次回读:
DNS-server0 : 192.168.10.254
DNS-server1 : 8.8.8.8 <- 确认写入成功
没有回读的变更等于没做——因为你不知道它到底生效了没有。这个习惯也顺带抓出了不少隐藏问题(见第五章)。
四、实战案例:一次完整的「检测 → 变更 → 验证」
以下是一次真实会话完成的三项变更,过程可以完整反映程序的工作方式。
目标一:配置 SW1 的接口地址池,可用地址 100~250
VRP 的接口地址池不支持直接写「起止地址」,标准手法是dhcp select interface拿到整个网段,再用excluded-ip-address把两端挖掉:
interface Vlanif10
dhcp select interface
dhcp server excluded-ip-address 192.168.10.1 192.168.10.99 <- 挖掉 1~99
dhcp server excluded-ip-address 192.168.10.251 192.168.10.253 <- 挖掉 251~253
回读结果精确对上了预期:Total 253 / Idle 151 / Disable 102——可用地址恰为 100~250 共 151 个。Vlanif20 同样处理。
一个容易踩的坑:Vlanif20 的池号是 Pool-No 1 而非 0,说明设备上还有别的池,回读时不能想当然。
目标二:补充 DNS = 各网段网关 + 8.8.8.8
interface Vlanif10
dhcp server dns-list 192.168.10.254 8.8.8.8
一条命令同时下发主备 DNS,display ip pool 中 DNS-server0 / DNS-server1 双字段回显正确。
目标三:R1 补默认路由
下发前先做下一跳存在性核查——display arp interface GigabitEthernet0/0/1:
10.10.10.1 0050-56c0-0008 Dynamic
10.10.10.2 0050-56fa-e47b Dynamic <- 目标下一跳,真实存在
两台设备都能正常回 ARP(华为 OUI 0050-56xx),二层确认有真实设备,说明这条路不会因 ARP 解析失败而失效。确认后才下发:
ip route-static 0.0.0.0 0.0.0.0 10.10.10.2
回读路由表,0.0.0.0/0 Static 60 RD 10.10.10.2 GE0/0/1——RD 标志表明路由已装入转发平面,真正生效,而不是只躺在配置里。
这一手「ARP 探活」很值得说:当 ICMP 被上游设备过滤时(本环境 10.10.10.1/.2 都 ping 不通),ping 会给出「设备不存在」的误导性结论,而 ARP 表能穿透这一层——二层有没有这台机器,ARP 说了算。
五、程序主动告诉你的「坏消息」
这套程序不只会执行命令,它还会在验证阶段主动暴露那些「命令成功但业务不通」的情况。同一次会话中有两个典型:
其一:8.8.8.8 实测不可达。默认路由配置成功、路由表生效,但 ping -c 3 8.8.8.8 是 3 发 0 收,tracert 全跳超时。程序没有止步于「配置已下发」,而是明确标注:路由配置本身正确,但外网可达性未通过验证,并把可能原因按可能性排序(上游无回程路由 / 出口未放通 NAT / 下一跳选错)。
其二:网关也是 DNS 地址 ≠ 网关提供 DNS 服务。按要求把首选 DNS 设成了网关地址,程序提醒:S5700 只负责「告知」客户端它本身不做 DNS 解析。若网关上没有真正运行 DNS 服务,客户端会先超时再回落 8.8.8.8——而 8.8.8.8 当前也不通,结果是「看起来配好了,实际解析很慢或失败」。
这类「提醒」才是运维助手真正的价值:命令回显说「成功」,但业务到底通不通,是两回事。
六、变更台账与边界
每次配置下发,程序都会逐条返回执行结果并标注持久化状态,一份清晰的台账随会话自然形成。本次会话的成果如下:
设备 | 变更内容 | 条数 | 持久化 |
SW1 | dhcp enable + Vlanif10/20 接口地址池(excluded ×4、dns-list ×2) | 7 | 仅运行配置 |
R1 | 默认路由 0.0.0.0/0 → 10.10.10.2 | 1 | 仅运行配置 |
同时明确列出未做的事:没动接口 IP、VLAN、链路类型,没删任何既有配置,没执行 save。「没做什么」和「做了什么」同样重要——这是可审计性的另一半。
关于能力边界,也应当坦率说明:
- 程序管理的是运行配置,持久化必须由你确认后单独 save;
- 它不能验证业务层连通性(比如 8.8.8.8 是否真通、DNS 是否真能解析),这需要上游设备的配合或真实流量验证;
- 对网络规划层面的判断(哪台设备才是真正的出口),它只能给出「基于 ARP 存活」的证据,最终取舍仍需人来拍板。
七、小结
这套程序的设计哲学可以概括成一句话:把「看」做到零成本,把「改」做到零意外。
- 读写分离,让巡检毫无顾虑;net_exec 与 run_command 双向引导,通道用错会被当场纠正;
- 三级命令管控 + 运行/启动配置分离,让误操作有物理闸门、让变更可回滚,设备侧 [Y/N] 交互由程序自动应答;
- 强制先读后写、写后回读,让每一次变更都有据可查;
- 懂 VRP 方言,认 ^ 报错、会用 | include、自动关分页,不做 Linux 习惯的生搬硬套;
- 敢于报告「配置成功但业务不通」,把通不通、好不好的判断权交回给人。
支撑这些行为的,是一套不依赖真机的测试体系:25 项假服务单测覆盖三态登录、安全拒绝与 Y/N 交互全路径,随时可回归;13 项 eNSP 真机冒烟覆盖巡检、下发、确认拒绝与错误回显判定。能力不是演示出来的,是测出来的。
对网工而言,这不是一个「帮你敲命令的机器人」,而是一位守规矩、会记账、还愿意说真话的搭档。