ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Python网工自动化运维:用Netmiko实现批量配置与备份

2026/9/19 6:21:34 拓冰建站 浏览量
Python网工自动化运维:用Netmiko实现批量配置与备份 简介这是一份面向网络工程师与运维人员的 Python 自动化运维学习笔记专门解决日常网络设备批量配置、远程管理与自动化脚本落地等实际问题。内容从 Python 安装、基础语法、数据类型、正则表达式、函数与模块到文件读写和异常处理均有覆盖并重点讲解 Telnetlib、Paramiko 模块的远程登录、命令执行与异常处理案例章节内代码示例丰富同时介绍 NETCONF/YANG 协议及 iMaster NCE-Campus 开放 API适合具备一定编程基础或正在转型网络自动化的技术人员。压缩包内为 1 个 PDF 文档大小 13.3MB目录按章节组织从环境搭建到进阶应用层次清晰便于按序学习或作为手边速查手册。目前已有 480 人学习读者可以从中获得可直接运行的脚本思路、设备配置管理操作方法以及对设备批次管理、自动化巡检、配置备份等任务的落地认知。1. Python 网工自动化运维用一个脚本把重复操作一次跑完在网工群里出现频率最高的提问往往不是哪条命令怎么拼而是同一段配置要在几十台交换机上重复操作。有人开了五个 SecureCRT 标签页手动粘贴有人把 show 命令的输出复制进 Excel 慢慢核对我这边一般直接写一个 Python 脚本把设备列表和要执行的命令一并传进去几分钟后收工。这份笔记想讲清楚的就是网工怎么用 Python 把配置下发、状态采集和配置备份这三件高频工作串成一条能长期维护的自动化运维流水线。文章不会去拼凑某个现成项目的源码而是沿最稳妥的从业路线展开先搭好本地 Python 环境再选适合网络设备的 SSH 库写单台设备的连接脚本扩展到批量并发最后把纯文本输出解析成结构化数据。适合刚接触 Python 的网工也适合想把手动巡检脚本整理成可维护工具的运维工程师。读完至少能有一个跑得通的配置备份脚本也知道后续该往哪个方向添砖加瓦。2. 搭好 Python 网工自动化运维的本地环境版本、虚拟环境与库选型2.1 先选解释器同一台机器上的 Python 3.8 与 3.12 不要混用网工初学 Python 遇到的第一个问题不是不会写代码而是命令行里到底哪个 Python 在生效。Windows 环境尤其混乱Microsoft Store 装了一个公司安全软件塞了一个Anaconda 又自带一个打开终端输入 python 时经常不知道自己进了哪套库。也见过最多的一条提示是“python was not found; run without arguments to install from the Microsoft Store”这通常不是没装 Python而是没有把解释器路径加进 PATH。解决方法是去设置里的 App execution aliases 把两个 python.exe 别名关掉或者重新运行安装包并勾选 Add python.exe to PATH。我自己在 Windows 和 Linux 上固定用 Python 3.10 或 3.12不追最新也不碰太老。Netmiko、TextFSM 这些库在 3.10 和 3.12 上都已经验证够稳没必要为了“兼容老环境”把自己卡在 3.6。Linux 上优先用发行版的 python3-pip 包不要源码编译安装 Python否则库路径和系统 Python 混在一起后面每次装包都要怀疑人生。装完先执行 python --version 和 pip --version确认两个命令指向同一套解释器。这一步做完后面 import 模块时至少一半的 ModuleNotFoundError 不会再出现。开发环境建议直接落到编辑器上。VSCode 里按 CtrlShiftP 打开命令面板选择 Python: Select Interpreter再指定刚才建好的虚拟环境PyCharm 则在 Settings 的 Project 下的 Python Interpreter 里切换。如果编辑器里能 import 成功、终端运行却报 ModuleNotFoundError基本都是解释器路径没对齐。2.2 网工自动化运维的 Python 库对比Paramiko、Netmiko、Nornir、NAPALM先把概念理清。Paramiko 是最底层的 SSH 库负责传输、认证和会话管理但它不懂网络设备的提示符是什么。Netmiko 建立在 Paramiko 之上加入了设备类型、提示符匹配、分页处理和错误识别面向 CLI 操作。Nornir 是一个并发调度框架用来管理多台设备并行执行任务本身不直接连设备而是配合 Netmiko 或 NAPALM。NAPALM 把设备配置和状态抽象成统一模型适合对接监控平台或 Ansible 这类上层工具。库定位适合场景上手成本ParamikoSSH 协议层底层调试、自定义协议高Netmiko网络设备 CLI 封装日常配置下发、采集、备份低Nornir并发与任务编排上百台设备批量执行中NAPALM配置模型抽象监控联动、合规检查中从网工自动化运维的角度看初期只需要 Netmiko理由很直接这个库单独就能完成连接、发命令、收完整输出三件事。等设备数量越过一百台再把 Nornir 加进来承担并发调度。至于 Ansible它是一条单独的自动化运维项目路线适合模板化配置下发最终用户可以不写 Python 就套用模板而 Python 脚本更适合临时采集、多厂商差异处理这类胶水场景。学习笔记的主线既然放在 Python 侧就先把 Netmiko 吃透Ansible 之后随时可以再补。我一般不建议把选型当成非黑即白。生产环境里经常是 Netmiko 负责下发命令Nornir 负责并发控制Ansible 负责最终流程编排和审计三者是互补关系。你在笔记阶段只需要把一个库用熟其余都是沿着同一套 SSH 和 CLI 知识体系长出来的切换成本并不高。2.3 最小安装命令netmiko、textfsm、ntc-templates 装齐python -m venv ~/.venvs/netauto source ~/.venvs/netauto/bin/activate pip install --upgrade pip pip install netmiko textfsm ntc-templates这段命令创建了一个名为 netauto 的虚拟环境并激活它然后把三个库装进这个环境。netmiko 提供面向网络设备的 SSH 连接与命令收发textfsm 负责把文本输出按模板转换成结构化字段ntc-templates 是一套从真实设备输出中总结的 TextFSM 模板集。不需要手动指定版本默认安装当前稳定版即可三个库之间的依赖已经互相验证过。显式安装 textfsm 还有个好处是后续要自己写模板时可以直接 import textfsm不需要再查一遍依赖关系。安装完成后用一行代码验证环境是否可用from netmiko import __version__ print(__version__)如果当前虚拟环境里能正常打印版本号说明环境就绪。Linux 系统上安装 Python 时如果缺少 pip执行 apt install python3-pip 或 yum install python3-pip 补齐即可Windows 上更省事安装包里默认带 pip只要 PATH 配好就能直接用。3. 用 Netmiko 批量操作设备从单台连接到并发下发3.1 最小可用的单台设备连接脚本一个能直接跑的 Netmiko 脚本长这样from netmiko import ConnectHandler import getpass device { device_type: cisco_ios, # 思科 IOS华为写 huaweiH3C 写 hp_comware host: 192.168.10.10, # 设备管理地址 username: neteng, password: getpass.getpass(SSH password: ), # 交互输入不落盘 secret: getpass.getpass(Enable password: ), # enable 密码 port: 22, timeout: 20, # 连接超时单位秒 fast_cli: False, # 慢速网络下也保证完整回显 } conn ConnectHandler(**device) conn.enable() output conn.send_command(show ip interface brief) conn.disconnect() print(output)这个脚本做的事依次是构造设备参数字典传给 ConnectHandler 建立 SSH 会话enable() 进入特权模式用 send_command 发送一条只读命令最后 disconnect 释放连接。device_type 是最关键的参数它决定 Netmiko 用哪套提示符匹配规则和交互习惯填错会直接卡在认证后的提示符识别上。常见取值如下厂商device_typeCisco IOS/IOS-XEcisco_iosCisco IOS-XRcisco_xrHuawei VRPhuaweiH3C Comwarehp_comwareRuijieruijie密码用 getpass 从终端输入而不是写死在代码里避免脚本泄露进版本库。如果设备已开启 SSH key 登录也可以把 password 换成 key_file 参数指向私钥文件路径。fast_cli 设为 False 会让 Netmiko 使用更慢但更稳的命令交互方式延迟较大的链路尤其重要。3.2 send_command 与 send_config_set只读命令和配置命令各走各的路Netmiko 把命令分成两类。send_command 用来发 show、ping、display 这种只读命令返回的是字符串send_config_set 用来发配置命令它会自动进入配置模式逐行输入内容再退出配置模式。混用这两类方法最常见的报错是“提示符不匹配”因为配置模式下显示的 prompt 和普通模式不同。config_cmds [ interface GigabitEthernet0/1, description To_Core_SW, switchport mode trunk, switchport trunk allowed vlan 10,20,30, ] conn.send_config_set(config_cmds) # 返回每条命令的回显 conn.save() # 思科 IOS 下等价于 write memory以思科 IOS 为例send_config_set 内部先发送 configure terminal再把列表里的命令逐条发送最后用 end 或 Ctrl-Z 退出。save() 在 IOS 上执行 write memory把 running-config 持久化。华为 VRP 下对应的是 save 命令Netmiko 同样封装了 save() 方法只是内部命令不同。配置结束后可以先不下发保存等巡检脚本确认没有报错再单独执行这样回滚更容易。这里有一个容易踩的坑不要在已处于配置模式的连接里继续调用 send_command。因为 send_command 会等待用户态提示符而设备还停在 (config-if)#两边对不上就会超时。要混合执行时用 send_config_set 处理所有配置命令用 send_command 只处理 show 命令。3.3 多设备并发的正确姿势与最大线程数批量下发最慢的做法是 for 循环串行连接三十台设备一台一台等每台三秒也要一分半钟。实际场景动辄上百台串行不可接受。Netmiko 本身是阻塞式模型但 SSH 会话大部分时间都在等待网络 I/O所以可以用线程池并发把时间降下来。from concurrent.futures import ThreadPoolExecutor, as_completed def execute_one(device): conn ConnectHandler(**device) try: output conn.send_command(show version) return device[host], output.splitlines()[0] finally: conn.disconnect() with ThreadPoolExecutor(max_workers5) as pool: futures {pool.submit(execute_one, device): device[host] for device in device_list} for future in as_completed(futures): host, first_line future.result() print(host, -, first_line)ThreadPoolExecutor 提交的是 execute_one 函数每个线程维护一个独立 SSH 连接。as_completed 会在任意一个任务结束时立即返回结果所以不需要等待最慢的那台设备。max_workers 建议设 5 到 10不要盲目调大。真实网络设备的管理面 CPU 有限并发太高会导致 SSH 握手超时严重时设备网页管理也会变卡。注意并发脚本跑在生产网之前先拿三到五台测试设备验证并把 max_workers 从 2 开始逐步调高。很多现场事故不是脚本逻辑错而是同一时间点向设备管理面打太多连接。4. 把 show 输出变成结构化数据TextFSM 解析与配置备份4.1 用 TextFSM 模板把 show interface 输出拆成字段SSH 返回的 show 输出本质是纯文本。直接把整段文字存进文件方便但想统计接口 down 数量、对比前后状态差异就需要先把文本解析成字段。Netmiko 集成了 TextFSM配合 ntc-templates 可以做到开箱即用from netmiko import ConnectHandler device { device_type: cisco_ios, host: 192.168.10.10, username: neteng, password: YourPassword, } conn ConnectHandler(**device) raw_output conn.send_command(show interfaces) parsed conn.send_command(show interfaces, use_textfsmTrue) conn.disconnect() for interface in parsed: print(interface[interface], interface[link_status], interface[protocol_status])use_textfsmTrue 会让 Netmiko 自动从 ntc-templates 里找对应平台和命令的模板把输出解析成列表每个元素是一个字典字段名由模板定义。ntc-templates 覆盖了 Cisco IOS、华为 VRP、H3C 等主流设备的高频 show 命令比如 show running-config、show version、show ip interface brief。解析结果可以直接按列导出成表格或写入数据库。如果没有现成模板也可以自己写一个最简单的 TextFSMValue INTERFACE (\S) Value LINK_STATUS (up|down|administratively down) Value PROTOCOL_STATUS (\S) Start ^${INTERFACE}\s${LINK_STATUS}\s\S\s\S\s${PROTOCOL_STATUS} - Record这个模板定义了三个字段Start 状态下的正则行负责匹配一行接口输出匹配成功后记录一条数据继续下一行。自己写模板前先拿真实设备输出对照不要用想象出来的格式去调正则否则换到新版本设备固件时很容易误配。4.2 配置备份脚本拉取、落盘、按日期归档配置备份是网工自动化运维里投入产出比最高的一件事。脚本思路很简单连接设备执行 show running-config把返回的字符串按“IP_日期.cfg”落盘。import os import time from netmiko import ConnectHandler backup_dir fconfigs/{time.strftime(%Y%m%d)} os.makedirs(backup_dir, exist_okTrue) for dev in device_list: conn ConnectHandler(**dev) conn.enable() run_cfg conn.send_command(show running-config) conn.disconnect() file_path f{backup_dir}/{dev[host]}.cfg with open(file_path, w) as f: f.write(run_cfg) print(file_path, saved)每次运行都会生成一个按日期命名的目录不会覆盖历史文件。第二天的备份可以与前一天的目录做 diff得到一份“两天间的配置变化清单”这是变更审计里非常关键的材料。归档目录建议同时保留清理策略比如只保留最近 30 天的目录避免磁盘被无数个 cfg 文件占满。4.3 用 crontab 或 Windows 计划任务把备份固定成例行动作脚本写完只是开始定时执行才叫自动化运维。Linux 上编辑 crontab0 3 * * * cd /home/neteng/netauto /home/neteng/netauto/.venv/bin/python backup_script.py backup.log 21这一行的含义是每天凌晨三点切换到项目目录用虚拟环境里的 python 执行备份脚本将标准输出和错误日志追加到 backup.log。关键是中间那一段要用虚拟环境内 python 的绝对路径因为 crontab 环境的 PATH 不包含当前 shell 的配置直接写 python 很可能找到系统自带的另一套解释器。Windows 对应的做法是打开任务计划程序新建任务触发器选每天凌晨操作里填入解释器完整路径和脚本路径。每周抽出几分钟去看 backup.log 和执行结果比检查文件是否生成更有价值。日志里同时记上每台设备的执行耗时如果某台设备连续几天耗时翻倍多半是网络质量下降或设备 CPU 高这也是巡检数据里一个很好的监控指标。5. 网工排错最常碰到的 Netmiko 问题5.1 连接失败先查这四样东西Netmiko 报 timeout 或者 authentication failed 时我先按固定顺序查四样东西设备类型是否填对。device_type 填错就不会走正确的提示符匹配很多 auth failed 其实卡在这一步。账号有没有远程登录权限。VTY 里 access-class 或 login local 配置限制都会导致握手后立刻断开。密钥是否正确。更换过 enable 或 SSH key 但没有同步更新脚本。管理网是否可达。设备地址漂移、防火墙策略变更都是常见原因。前两样看配置后两样可以先用系统命令验证ssh -vvv neteng192.168.10.10 ping -c 3 192.168.10.10ssh -vvv 能看到完整的握手过程比在 Netmiko 里猜快得多。如果手工 SSH 能登录但 Netmiko 不行多半是提示符不匹配或算法协商问题。此时打开 Netmiko 日志定位最快import logging logging.basicConfig(levellogging.DEBUG)DEBUG 级别会打印出 Netmiko 发送和接收的原始报文能看到它在等待哪个提示符、设备实际回的是什么。如果日志里出现类似 no matching key exchange method 的说法说明设备 SSH 算法太旧需要在 device 字典中添加 Paramiko 层算法设置或先升级设备 SSH 配置。5.2 设备被卡在分页模式里发送命令前关闭分页很多设备默认开启分页命令输出超过一屏就停在那里等待输入空格Netmiko 等不到下一个提示符脚本就会一直挂到超时。解决办法是在建立连接后立刻关闭分页。conn.send_command(terminal length 0) # Cisco IOS conn.send_command(screen-length 0 temporary) # 华为 VRPCisco IOS 用 terminal length 0华为 VRP 用 screen-length 0 temporary。如果你用的设备类型没有对应命令查一下厂商文档里“关闭分页”的写法把它放在发任何 show 命令之前。这个步骤最好封装在连接函数里避免每次手工加。和分页问题相关的还有隐藏超时。设备 VTY 线路里的 exec-timeout 太短时Netmiko 刚完成登录就被设备主动断开处理方式是把 exec-timeout 临时调大到 10 分钟再测试。如果设备在虚拟化环境里出现回显乱码或输出缺失可以在设备参数里加 global_delay_factor2让每条命令之间的延迟翻倍解决吞字符问题。5.3 单个设备报错不能中断整个批量任务批量脚本最怕的场景是一台设备网络不通整个程序的异常直接抛出后面的设备全部没跑。正确的做法是把每台设备的执行包进独立 try/except失败信息单独收集最后统一输出。failed [] for dev in device_list: try: run_backup(dev) except Exception as exc: failed.append((dev[host], str(exc))) else: print(dev[host], ok) if failed: print( Failed hosts ) for host, reason in failed: print(host, reason)这个结构保证了单台设备的报错不会中断整批任务同时保留失败记录方便事后重跑。生产环境里我通常还会把失败的 host 列表写进一个 failed.txt下次定时任务开始时先读它只重跑失败设备。这样就把“采集-失败-补采”的循环补完整了。6. 把配置差异上报写进 Python 网工自动化运维脚本最后一个技巧很实用用配置差异上报把“下发配置”这个动作变成一个能闭环验证的流程。脚本下发完配置后再抓取一次设备的 running-config与期望配置做对比结果以统一格式输出。import difflib with open(expected/192.168.10.10.cfg) as f1: expected f1.read().splitlines() with open(backup/20240102/192.168.10.10.cfg) as f2: actual f2.read().splitlines() diff difflib.unified_diff(expected, actual, fromfileexpected, tofileactual, lineterm) for line in diff: print(line)difflib 的 unified_diff 输出会以 或 - 标出实际配置里多出和缺失的行最前面是变更位置。把这些行存成 ChangeRecord.md 或者通过 SMTP 发送到值班邮箱就有了一个最简的配置审计循环。验证脚本是否真的生效还要看设备运行状态而不是只看配置文本。例如改了接口的 trunk vlan配置 diff 能确认命令已写入但要确认最终生效可以在同一脚本里再发一次 show interface trunk检查期望的 VLAN 是否出现在允许列表中。我把这个检查动作封装成一个 verify(device, expected_vlan) 函数返回 True 或 False并在批量任务结束后把失败项汇总打印。这里有个可复用的判断标准配置能否回滚。每次下发配置前先自动备份当前配置到带时间戳的文件再执行变更最后根据 diff 结果决定保留或回滚。回滚时只要把之前的备份文件用 send_config_set 重新灌回设备即可。对网工来说这条“备份-变更-校验-回滚”的链路比任何单个命令都更有长期价值。脚本本身不要越滚越复杂。建议把设备连接、命令列表、差异对比分成三个独立文件设备列表用 YAML 或 CSV 维护这样新接入一台设备时不需要改 Python 代码。这也是网工面试里被问到模块设计时有线上的工程师会先拿出来的回答框架可读性大于花哨可维护性大于一次性技巧。本文还有配套的精品资源点击获取