4. Netmiko批量运维入门
Netmiko 是 Paramiko 之上的一层“多厂商 SSH 驱动库”,它把不同厂商设备在登录提示符、分页机制、配置模式切换、保存命令上的差异封装成统一接口。对网络自动化来说,这意味着我们不必为 Cisco IOS、华为 VRP、H3C Comware、Juniper Junos 各写一套 Paramiko 交互逻辑,而是用同一套 Python 代码,通过 device_type 参数切换驱动,完成 show 命令采集、配置下发、分页处理、超时与异常控制,最终实现批量配置备份。
理解 Netmiko 的关键,是理解它内部的一次连接生命周期:建立 SSH 会话 → 识别提示符 → 进入特权/配置模式 → 发送命令 → 处理分页 → 读取回显 → 断开。下图展示了这一信号链与四类厂商驱动的对应关系,以及分页、超时、异常在链路中的位置。
连接四类厂商设备
Netmiko 用 ConnectHandler 建立连接,核心参数是 device_type。不同厂商的驱动名不同,但调用方式完全一致。下面是一个连接 Cisco IOS 设备并执行 show 命令的最小示例:
from netmiko import ConnectHandler
device = {
"device_type": "cisco_ios",
"host": "192.168.1.1",
"username": "admin",
"password": "Cisco@123",
"secret": "Enable@123", # enable 密码
"port": 22,
"conn_timeout": 10,
"read_timeout": 30,
}
with ConnectHandler(**device) as conn:
conn.enable() # 进入特权模式
output = conn.send_command("show version")
print(output)
华为、H3C、Juniper 只需替换 device_type:华为用 huawei,H3C 用 hp_comware,Juniper 用 juniper_junos。注意 Junos 没有传统意义上的 enable 模式,conn.enable() 对 Junos 不适用,应直接发送 show 命令或进入 configure 模式。
发送 show 命令与配置命令
Netmiko 提供两个核心方法:send_command() 用于发送 show 类只读命令,返回字符串;send_config_set() 用于发送配置命令列表,自动进入配置模式、逐条下发、退出配置模式。例如给华为交换机批量下发 VLAN 配置:
config_commands = [
"vlan 100",
"description AUTO_VLAN_100",
"quit",
]
conn.send_config_set(config_commands)
conn.save_config() # 华为执行 save,Cisco 执行 write memory
send_config_set() 内部会根据驱动自动处理 system-view(华为/H3C)、configure terminal(Cisco)、configure(Junos)等模式切换,这是 Netmiko 相比裸 Paramiko 最大的价值。
分页、超时与异常处理
分页是批量运维中最常见的“坑”。Cisco 输出满屏出现 --More--,华为/H3C 出现 ---- More ----,如果不处理,send_command() 会一直等待直到 read_timeout 超时。Netmiko 默认在连接时发送 terminal length 0(Cisco)、screen-length 0 temporary(华为/H3C)来关闭分页,但部分老设备或权限受限账号可能失败,此时可显式设置:
conn.send_command("show running-config", expect_string=r"#")
# 或手动关闭分页
conn.send_command("terminal length 0")
超时参数需要区分三类:conn_timeout 控制 TCP 建链时间,auth_timeout 控制认证时间,read_timeout 控制命令回显读取时间。批量场景下建议 conn_timeout=10、read_timeout=60,避免大配置读取被误判超时。
异常处理必须逐台隔离。常见异常包括 NetmikoTimeoutException(连接或读取超时)、NetmikoAuthenticationException(账号密码错误)、ConfigInvalidException(配置命令被设备拒绝)。批量任务中,一台设备失败不应中断整个循环:
from netmiko import NetmikoTimeoutException, NetmikoAuthenticationException
for dev in devices:
try:
with ConnectHandler(**dev) as conn:
cfg = conn.send_command("show running-config")
save_backup(dev["host"], cfg)
except NetmikoAuthenticationException:
log.error(f"{dev['host']} 认证失败")
except NetmikoTimeoutException:
log.error(f"{dev['host']} 连接超时")
except Exception as e:
log.error(f"{dev['host']} 未知异常: {e}")
批量配置备份实战
把上述能力组合起来,就是一个可用的批量备份脚本。核心思路是:设备清单用列表或 CSV 维护,每台设备独立连接、独立采集、独立落盘,文件名包含主机名与日期,便于版本追溯。下面给出一个可直接参考的备份函数:
import os, datetime
from netmiko import ConnectHandler
BACKUP_DIR = "backup"
def backup_device(dev):
host = dev["host"]
today = datetime.date.today().isoformat()
out_dir = os.path.join(BACKUP_DIR, today)
os.makedirs(out_dir, exist_ok=True)
with ConnectHandler(**dev) as conn:
if dev["device_type"] == "cisco_ios":
conn.enable()
cfg = conn.send_command("show running-config")
ext = "cfg"
elif dev["device_type"] in ("huawei", "hp_comware"):
cfg = conn.send_command("display current-configuration")
ext = "cfg"
elif dev["device_type"] == "juniper_junos":
cfg = conn.send_command("show configuration")
ext = "conf"
else:
raise ValueError("不支持的 device_type")
path = os.path.join(out_dir, f"{host}.{ext}")
with open(path, "w", encoding="utf-8") as f:
f.write(cfg)
return path
执行后,备份目录结构如下(示例):
backup/
└── 2025-01-15/
├── 192.168.1.1.cfg # Cisco R1
├── 192.168.1.2.cfg # 华为 SW1
├── 192.168.1.3.cfg # H3C SW2
└── 192.168.1.4.conf # Juniper FW1
interface、vlan、hostname)。建议在脚本末尾打印每台设备的备份路径与字节数,便于快速核对。掌握以上内容后,你已经可以用 Netmiko 完成四类主流厂商设备的连接、命令下发、分页处理、异常隔离与批量备份。下一阶段可以在此基础上引入并发(如 concurrent.futures)提升大批量设备采集效率,但并发前务必先确认单台设备的超时与异常处理已经稳定。