2. 网络设备交互基础
网络自动化的第一步,是让 Python 程序能够与网络设备“说上话”。不同协议决定了通信的通道、认证方式、数据格式和可操作范围。理解这些差异,才能在实际运维中选择合适的连接方式,并正确处理交互式命令与配置模式切换。
四种主流交互协议的核心差异
Telnet 是最早的远程登录协议,基于 TCP 23 端口,所有数据(包括用户名和密码)以明文传输。它的优势是实现简单、兼容性极好,几乎所有网络设备都支持;缺点是安全性差,只适合实验室或隔离管理网络。Python 标准库 telnetlib 可直接使用,但该库在 Python 3.13 中已被移除,实际工程中更推荐用 socket 自行封装或使用第三方库。
SSH 是目前主流的远程管理协议,默认 TCP 22 端口,通过加密通道传输数据,支持密码和密钥认证。网络设备上的 SSH 通常提供交互式 shell,也支持执行单条命令。Python 中 paramiko 是最常用的 SSH 库,它封装了传输层加密、认证、通道和会话,适合批量登录设备执行命令。
NETCONF 是基于 SSH 的应用层协议,默认使用 830 端口,采用 XML 编码,通过 <rpc> 和 <rpc-reply> 消息交换配置与状态数据。它面向“配置数据库”模型,支持 candidate、running、startup 等数据存储,适合结构化配置管理。Python 中常用 ncclient 库。
RESTCONF 则把 NETCONF 的数据模型映射到 HTTP 方法上,使用 GET、POST、PUT、PATCH、DELETE 操作 YANG 模型数据,返回 JSON 或 XML。它更适合与 Web 系统、控制器平台集成,Python 中可用 requests 直接调用。
用 socket 理解连接的本质
无论上层协议多复杂,底层都是 TCP 连接。socket 模块让我们直接观察“连接—发送—接收—关闭”这一过程。下面示例连接一台设备的 22 端口,仅验证可达性,不进行 SSH 协商:
import socket
host = "192.168.1.1"
port = 22
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
try:
s.connect((host, port))
banner = s.recv(1024)
print("Banner:", banner.decode(errors="ignore").strip())
except socket.timeout:
print("连接超时,检查 IP、端口或 ACL")
except ConnectionRefusedError:
print("端口拒绝连接,服务可能未开启")
finally:
s.close()
运行后若返回类似 SSH-2.0-Cisco-1.25 的 banner,说明 TCP 可达且 SSH 服务已监听。这一步常被用作批量巡检的前置探测:先判断设备是否在线、端口是否开放,再决定是否发起完整 SSH 会话。
paramiko 建立 SSH 会话与命令执行
paramiko 的核心对象是 SSHClient。它负责建立传输、认证、打开通道。下面示例使用密码认证登录设备,执行 display version 并读取输出:
import paramiko
import time
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(
hostname="192.168.1.1",
port=22,
username="admin",
password="Admin@123",
timeout=10,
look_for_keys=False,
allow_agent=False
)
shell = client.invoke_shell()
time.sleep(1)
shell.recv(65535)
shell.send("display version\n")
time.sleep(2)
output = shell.recv(65535).decode(errors="ignore")
print(output)
client.close()
这里使用 invoke_shell() 而不是 exec_command(),是因为网络设备通常需要进入交互式 shell 才能切换视图。注意 time.sleep() 只是教学简化,生产环境应使用 recv_ready() 轮询或 select 等待数据,避免因设备响应慢导致读取不完整。
交互式命令与配置模式切换
网络设备的命令行通常分为用户视图、系统视图、接口视图等多层模式。以华为设备为例,提示符从 <Huawei> 变为 [Huawei] 表示进入系统视图,再进入接口视图变为 [Huawei-GigabitEthernet0/0/1]。Python 脚本必须根据提示符判断当前模式,再发送对应命令。
一个实用的模式切换与配置下发片段如下:
def send_cmd(shell, cmd, wait=1.5):
shell.send(cmd + "\n")
time.sleep(wait)
return shell.recv(65535).decode(errors="ignore")
send_cmd(shell, "system-view")
send_cmd(shell, "interface GigabitEthernet0/0/1")
send_cmd(shell, "description Python_Auto_Test")
send_cmd(shell, "return")
send_cmd(shell, "save", wait=3)
判断配置是否成功,不能只看有没有回显,而要检查返回内容中是否出现 Error、Unrecognized、Invalid 等关键字,同时确认提示符已回到预期层级。批量运维中,建议把“发送命令—等待—读取—校验”封装为统一函数,并对不同厂商维护提示符映射表。
socket 探测端口,再用 paramiko 建立会话;执行配置前先备份 running-config,配置后通过 display current-configuration interface 回读校验,形成“探测—连接—执行—回读”的闭环。