
简介面向网络运维与IT自动化人员提供一套基于Python与SSH协议的网络设备自动化管理实现方案尤其适用于中小型网络场景下路由器与交换机的批量配置与状态巡检。包体为单个docx文档大小1.89MB内容完整覆盖设计思路、环境搭建与核心代码可直接对照eNSP拓扑进行实操。方案以paramiko模块建立SSH连接借助re与time实现命令交互与输出解析可实现设备版本、接口状态、IP地址、内存使用等信息的自动查询以及用户配置、访问控制和配置文件备份等自动化操作。通过华为eNSP模拟器与FreeSSHd组合验证帮助读者降低人工重复操作提升运维准确性。已有107人学习下载适合具备一定Python基础、希望拓展网络自动化技能的工程师及计算机专业学生。 设备多了以后光靠手敲命令逐台登录设备做配置、做巡检效率低不说还容易敲错。这几年我在网络运维岗上最大的一个体会就是凡是重复的、有规律的、需要批量执行的操作都值得用脚本去替代。Python配上SSH协议就是一套门槛最低、见效最快的自动化组合。这篇文章就围绕“Python SSH”这条路讲清楚网络设备自动化管理怎么做、为什么这么做、实际落地时会踩哪些坑。1. 整体设计与思路拆解1.1 网络运维的重复痛点为什么偏偏选SSH先别急着写代码想清楚一个问题网络设备自动化有很多种路子SNMP、NETCONF、RESTCONF、Telemetry都有各自的适用场景为什么日常工作中用得最多的反而是SSH原因不复杂。SNMP能帮你读取设备状态但改配置的能力很弱NETCONF/RESTCONF是好东西可不少老旧设备、低端设备压根不支持而SSH是几乎所有网络设备都标配的远程管理协议交换机、路由器、防火墙、无线控制器无论哪个厂商只要你平时能用SecureCRT或Xshell登录上去敲命令就说明设备一定开了SSH服务。这意味着你用Python的SSH库写一套脚本就能通吃全场设备不用关心设备是华为、H3C、思科还是锐捷只要它会用命令行交互就行。另外还有个现实因素运维现场往往有各种安全策略、跳板机、堡垒机很多环境下图形化网管接口不一定开放但SSH 22端口大概率是通着的。与其纠结要不要上一套重量级自动化平台不如先用手边的Python把SSH这条链路打通马上就能看到效率提升。1.2 用Paramiko还是Netmiko这个选择很关键确定走SSH这条路后首先要选Python库。Paramiko是Python生态里最底层的SSH协议实现它的定位是帮你建立SSH连接、执行命令、传输文件说白了就是给你一把“裸工具”。而Netmiko是建立在Paramiko之上的网络设备专用封装库它内置了几十种厂商设备类型的交互规则能够自动处理不同设备的命令行提示符、分页符、特权模式切换等差异。我自己的建议是如果你只是临时跑个命令、批量备份配置或者想深入理解SSH交互的过程用Paramiko没问题但如果目标是长期维护一套设备管理脚本一定要用Netmiko。原因很简单Netmiko帮你解决了一个特别烦人的问题——设备返回大量信息时分页暂停比如---- More ----用Paramiko你得自己手动发空格去翻页而Netmiko会默认关闭分页并自动处理这些交互细节。1.3 自动化脚本的设计思路在实际规划这套自动化工具时我遵循一个原则连接层、命令层、业务层三层分离。连接层统一负责SSH会话建立、认证、断开不管底层是Paramiko还是Netmiko对上提供统一的接口命令层负责执行具体命令、判断返回结果、处理异常业务层才是真正跟需求相关的部分比如“每日自动备份所有交换机配置”、“批量把几十台设备的NTP地址改掉”、“自动收集设备CPU和内存使用率”。这样做的好处非常明显三层分离之后更换连接库、增加新设备型号、修改业务命令相互之间都不会影响。哪怕你今天用的是华为设备明天要管理思科设备只要你把设备类型这个参数改掉脚本主体完全可以复用。2. 核心细节解析与实操要点2.1 设备登录认证密码和密钥两种方式的取舍SSH登录网络设备通常有两种认证方式密码认证和密钥认证。密码认证最容易理解账密配置好直接登录。但这里有个坑企业网络的设备账密往往有定期轮换的合规要求而且不同批次设备的密码可能还不一样。如果脚本里硬编码密码密码一换脚本就崩如果写在配置文件里文件本身又需要做好权限管控。密钥认证就灵活得多。网络设备支持在客户端生成一对RSA密钥把公钥配置到设备上之后SSH登录时只要客户端持有私钥就能免密登录。这样做的好处是脚本里不需要存密码认证凭据是密钥文件本身而且密钥可以设置独立的访问权限比如只允许指定账号通过该密钥登录。我在实际项目里面对上百台设备批量管理时几乎全部使用密钥认证。运维人员可以在自己的电脑或者跳板机上生成密钥对将公钥分发到每台设备的管理账号下。之后脚本运行时只要密钥文件路径配置正确无需任何交互输入密码就可以完成全部认证流程这在配合Jenkins定时执行任务时优势尤其突出。2.2 Netmiko核心参数配置Netmiko使用起来非常简单核心就是创建一个连接对象from netmiko import ConnectHandler device { device_type: huawei, host: 192.168.10.1, username: admin, password: your_password, port: 22, secret: enable_password, # 如果需要进入特权模式 timeout: 30, conn_timeout: 15, } conn ConnectHandler(**device)这里面的参数有讲究。device_type决定Netmiko用什么交互规则常见值有huawei、cisco_ios、hp_comware、ruijie_os等选项很多用之前最好去官方文档查一下你的设备型号对应哪个值。timeout指的是命令执行的超时时间conn_timeout是TCP连接建立的超时时间批量操作用的比较多的时候这两个超时建议设置得宽裕一些避免因网络抖动导致脚本大面积失败。再说说secret。华为设备进入系统视图不需要单独的特权模式但思科设备从用户模式进入特权模式需要执行enable命令。Netmiko的secret参数就是干这个用的。如果你的设备只需要普通命令就能完成操作可以不用这个参数。2.3 对设备返回信息的判读是自动化的核心执行命令后设备返回的信息可能是命令回显、也可能包含错误提示。脚本要做的不仅仅是“把命令发出去”更重要的是判断命令是否真的执行成功。Netmiko提供了一个send_command方法返回的是命令输出的文本。判断成败常用的手段是检查输出中是否包含特定的错误关键字比如% Unknown command、Error: Unrecognized command、Invalid input detected at ^ marker等。我写脚本时通常会把一个命令的输出标准定义好然后用in运算符做关键字匹配这是最简单也最可靠的办法。另外不少初学者容易忽略的一点是先进入设备的配置模式再执行配置命令。比如华为设备如果不先执行system-view就试图配置接口设备会直接报错。一些老牌厂商的模拟器环境对这种细节特别严格玩过eNSP的人都懂。所以脚本里配置类命令的序列往往是system-view、逐条下发配置、return或quit退出配置模式。3. 实操过程与核心环节实现3.1 环境准备与依赖安装动手之前先把Python环境准备好。Windows、Linux、macOS都可以Python 3.6以上版本就能顺利运行Netmiko。安装依赖只需要一条命令pip install netmiko paramikoNetmiko会自动把Paramiko作为依赖装上所以直接装Netmiko就够了。如果你在公司内网环境装不了PyPI源可以在有外网的机器上下载好wheel包再拷贝到内网机器本地安装。个人建议先把基础连通性测试做扎实再用脚本去连设备。具体做法是先用你平时习惯的SSH客户端Xshell、SecureCRT、MobaXterm均可手动登录目标设备确认账号、密码、端口、SSH协议版本都没有问题。这样脚本失败时你可以确定问题出在脚本侧而不是基础网络侧排查范围至少缩了一半。3.2 批量备份交换机配置这个脚本是我在运维日常中复用得最频繁的核心功能是批量登录多台设备执行display current-configuration华为或show running-config思科把输出保存为本地文件文件名带上设备名和日期。import os import datetime from netmiko import ConnectHandler devices [ {device_type: huawei, host: 192.168.10.1, username: admin, password: Pass123}, {device_type: huawei, host: 192.168.10.2, username: admin, password: Pass123}, ] today datetime.datetime.now().strftime(%Y%m%d) backup_dir fbackup_{today} os.makedirs(backup_dir, exist_okTrue) for dev in devices: host dev[host] print(f开始备份 {host} ...) try: conn ConnectHandler(**dev) conn.enable() # 如果需要进入特权模式 output conn.send_command(display current-configuration) conn.disconnect() filename os.path.join(backup_dir, f{host}_{today}.txt) with open(filename, w, encodingutf-8) as f: f.write(output) print(f{host} 备份成功文件{filename}) except Exception as e: print(f{host} 备份失败{e})这段代码里有一个细节值得说明文件保存编码用的是utf-8。华为设备返回的配置文本里包含中文备注时如果直接按系统默认编码Windows下是GBK保存后续用文本编辑器查看很容易乱码。统一用UTF-8保存配合VS Code或Sublime Text查看就没问题。3.3 批量修改设备配置备份是读取操作配置变更是写入操作风险系数完全不同。批量修改设备配置前我是强烈建议先把配置命令写在一个文本文件里脚本按需读取并逐条下发尽量减少在代码里硬编码命令的条数。这样命令的审核、变更留痕、后续维护都会方便许多。# commands.txt system-view ntp-service refclock-master 1.1.1.1 ntp-service unicast-server 202.118.1.1 return save force脚本读取该文件后用send_config_set方法一次性下发全部命令from netmiko import ConnectHandler from netmiko.exceptions import ConfigInvalidException device { device_type: huawei, host: 192.168.10.3, username: admin, password: Pass123, } with open(commands.txt, r, encodingutf-8) as f: commands [line.strip() for line in f if line.strip() and not line.startswith(#)] conn ConnectHandler(**device) output conn.send_config_set(commands) print(output) conn.disconnect()注意send_config_set和send_command的区别send_config_set专门用于发送配置类命令自动进入配置模式并退出配置模式send_command用于发送普通查询命令。如果你混用轻则命令不生效重则直接把设备搞进一个奇怪的模式里再往后执行什么都会报错。还有一点脚本里最后一行是save force。华为设备的配置修改后如果不保存重启就会丢失。save force会跳过交互确认直接保存配置。在实际操作中变更结束后是否立即保存需要根据变更管理流程来决定。有的场景要求先观察一段时间再保存如果脚本默认保存了反而可能让有问题的配置固化到设备里这一点务必要和你的变更策略对齐。3.4 批量巡检收集设备关键状态除了备份和配置巡检是另一个高频场景。用send_command执行display device、display cpu-usage、display memory-usage把结果汇总到一个汇总文件就能实现一个最简版本的“巡检机器人”。from netmiko import ConnectHandler devices [ {device_type: huawei, host: 192.168.10.1, username: admin, password: Pass123}, {device_type: huawei, host: 192.168.10.2, username: admin, password: Pass123}, ] with open(inspection_report.txt, w, encodingutf-8) as report: for dev in devices: host dev[host] report.write(f {host} \n) try: conn ConnectHandler(**dev) report.write(【CPU】\n conn.send_command(display cpu-usage) \n) report.write(【内存】\n conn.send_command(display memory-usage) \n) report.write(【设备信息】\n conn.send_command(display device) \n) conn.disconnect() except Exception as e: report.write(fERROR: {e}\n) report.write(\n)这个脚本的编写思路同样遵循“能并行就并行”的原则因为设备多的时候串行执行会特别耗时。但要注意并行只是把脚本挂个线程池Netmiko本身对单台设备的操作还是同步的。用concurrent.futures.ThreadPoolExecutor把每台设备丢到一个线程里去执行设备数量多的时候效率提升会非常明显。4. 常见问题与排查技巧实录4.1 认证失败与SSH配置问题SSH连接报认证错误排查思路应该按“网络可达 → 端口通 → 协议匹配 → 账密正确 → 授权足够”的链路逐层进行。先说网络和端口用ping测网络连通性用telnet ip 22测试端口是否可达。然后是SSH协议版本Python的Paramiko默认支持SSH v2如果你的设备只开了SSH v1认账就是谈不拢。账密问题则要检查设备账号是否被锁定、密码是否过期、是否配置了ACL限制管理地址。最后别忽略授权问题很多设备账号是低权限的只能看不能改执行配置命令就会报权限不足。密钥认证如果连不上优先检查密钥权限。在Linux跳板机上私钥文件的权限必须是600或400权限过宽SSH直接拒绝使用该密钥。Windows上用密钥时用ssh-keygen生成的私钥格式有些老设备不认需要转换成OpenSSH格式。4.2 命令输出超时或被截断批量执行命令时如果命令本身比较耗时比如display current-configuration在配置量大的设备上可能要好几秒默认超时时间可能不够。Netmiko的send_command可以显式设置超时时间output conn.send_command(display current-configuration, read_timeout60)如果命令返回的内容特别长还有一个隐藏问题终端宽度。设备默认的终端宽度可能是80列超宽部分会被折行或者截断导致输出的配置内容不完整。Netmiko在连接后会自动把终端宽度调整为较大的值通常是511列但如果你用Paramiko裸连就得记得手动设置。4.3 设备返回编码乱码SSH协议传输的是字节流Netmiko会按设备的编码规则解码。绝大多数设备默认是UTF-8但有些华为老设备会用GBK编码输出中文。如果你发现输出里中文全是乱码可以在Netmiko连接参数里加一个encoding参数试一下device { device_type: huawei, host: 192.168.10.1, username: admin, password: Pass123, encoding: gbk, }这个问题在手工操作时根本感知不到人眼能看懂乱码背后的意思脚本就完全不行。批量巡检时如果脚本里有关键字匹配逻辑一旦编码不对匹配必然失败甚至会把正常信息识别成异常信息。4.4 多厂商设备指令差异不同品牌设备命令差异很大这是网络自动化绕不开的痛。思科的show running-config对应华为的display current-configuration思科的接口模式对应华为的系统视图命令行的提示符也完全不同。Netmiko用device_type来屏蔽这些差异但它只能解决交互层的差异命令本身还是要你自己区分。我的做法是写一个简单的适配层把常用操作封装成统一的接口。例如def get_running_config(conn): if conn.device_type.startswith(huawei): return conn.send_command(display current-configuration) elif conn.device_type.startswith(cisco): return conn.send_command(show running-config) else: raise ValueError(f暂不支持该设备类型{conn.device_type})额外提醒一点华为设备的VRP版本和VRP8版本之间命令也有一定差异比如BGP、接口下的配置子命令有些地方不兼容。在写脚本前最好确认好设备的具体版型别想当然。5. 安全加固与方案扩展方向5.1 千万不要把密码硬编码进脚本开发机上的脚本拿来就能跑但这样的脚本一旦流传出去就等同于把全网设备的管理员密码公布出来了。代码仓库可能被员工误传、离职人员可能拷走脚本、测试服务器提升权限的机器可能被攻破任何一个环节出问题你的设备密码都会泄露。我习惯的替代方案是使用环境变量或者独立的配置文件。配置文件单独放并且设置严格的读写权限Linux下用chmod 600Windows下只给当前用户读写权限。脚本启动时从配置文件读取账密import os PASSWORD os.environ.get(DEVICE_PASSWORD, )如果公司有密码管理系统能通过API动态取密码那就更好了脚本执行时按需获取不落地存储这是最稳妥的办法。5.2 从脚本到平台化简单调度、记账、告警单台跑脚本只是第一步真正能发挥自动化价值的是让它定时运行、结果可追溯。用Windows自带的计划任务或者Linux的crontab可以每天凌晨自动执行配置备份脚本上班后打开备份目录检查文件大小和生成时间即可。更进一步可以把备份文件打上日期和时间戳通过Git提交到本地仓库。这样每天的配置变更都有历史记录设备配置被意外改坏时可以清楚地知道是哪一天、哪台设备、改了什么。这个思路看起来简单实际做下来会发现它的价值比预期大得多。如果公司已经有Jenkins也可以把脚本作为构建任务集成进去。把设备IP列表、命令文件当作参数配置一个定时触发器就能实现可视化的自动运维任务编排。网上搜“jenkins自动化部署”的热度一直很高很多人拿它做应用发布但做网络设备定时巡检同样是非常典型且实用的方向。5.3 与Ansible等主流自动化框架的配合如果你想走得更远可以了解一下Ansible。Ansible的网络模块底层也是走SSH但它的理念是用声明式的Playbook代替命令式脚本设备配置的最终状态用YAML描述Ansible负责计算差异、自动下发、返回结果。对比维度Python SSH脚本Ansible网络自动化上手门槛需要Python基础写逻辑灵活需要了解YAML和Ansible语法学习曲线陡峭设备适配自己处理命令和交互细节网络模块对主流厂商适配好但部分新模块验证不足灵活性高度灵活适合复杂自定义逻辑适合标准化的配置管理复杂逻辑需要用自定义模块补适合场景小型环境、快速开发、定制化操作大规模标准化设备管理和配置合规我的经验是先用Python脚本把自动化跑起来理解和掌握SSH交互的本质之后再决定要不要上Ansible。两个方案不是水火不容很多团队就是Python脚本处理临时性任务、Ansible负责常态化的配置部署配合得非常好。写在最后的心得网络运维的自动化最开始可能只是为了省事但真正跑起来之后你会发现它最大的价值不是“省掉手工敲命令的时间”而是把操作过程变成了可复现、可记录、可审计的资产。以前最怕的设备配置漂移、人为误操作、变更无记录这些问题在自动化面前都会被极大地收敛。如果你是从零开始我的建议是先不要贪多求全找一个对你最有价值的小场景下手。比如就从“每周自动备份一次核心设备配置”开始把这一个场景彻底做落地跑顺了之后再往批量配置、巡检报告、告警通知的方向拓展。网络自动化没有想象的那么玄乎它就是一步步把这些重复劳动交给脚本让你有更多时间去处理真正需要人的判断力和经验的复杂问题。本文还有配套的精品资源点击获取