Python脚本SSH批量登录交换机(地址不连续+异常处理)
在网络实验或运维场景中,经常需要对多台交换机进行批量配置,尤其是当交换机IP地址不连续时,手动登录每台设备配置不仅效率低下,还容易出现操作失误。本文将介绍如何使用Python脚本,通过SSH协议登录ENSP模拟器中的交换机,实现地址不连续设备的批量配置,并针对登录过程中可能出现的各种异常进行捕获和处理,让批量运维更高效、更稳健。
本文适合有一定Python基础和ENSP使用经验的网络爱好者/运维人员,核心实现基于paramiko库(SSH连接核心),全程贴合实际实验场景,包含完整的思路解析、代码实现、异常处理逻辑和实验验证步骤,最后会结合实际网络拓扑,说明脚本的应用场景,确保大家能直接复用、灵活修改。
一、实验环境准备
在编写脚本前,需先搭建好实验环境,确保Python环境与ENSP模拟器能够正常通信,为后续脚本运行奠定基础。
1.1 软件环境
-
操作系统:Windows 10/11(本文基于Windows环境演示,Linux/Mac环境操作类似)
-
Python版本:3.10
-
ENSP模拟器:1.3.00.100
-
核心库:Paramiko ,time ,getpass ,sys, os ,socket
1.3 ENSP交换机基础配置
要实现SSH登录,需先在ENSP的交换机上配置SSH服务(以华为S5700交换机为例),核心配置如下(每台需要批量配置的交换机均需执行):
system-view
stelnet server enable
aaa
local-user admin password cipher Huawei@123
local-user admin service-type ssh
local-user admin privilege level 15
quit
ssh authentication-type default password
user-interface vty 0 4
authentication-mode aaa
protocol inbound ssh
ssh user huawei service-type stelnet
quit
注意:每台交换机的管理IP需配置完成,且与运行Python脚本的主机处于同一网段,确保网络连通(可通过ping命令验证连通性)。
1.4 实验网络拓扑


二、核心需求分析
本次实验的核心需求的是解决“地址不连续的多台交换机批量SSH登录+配置+异常处理”,具体拆解为以下3点:
-
批量处理:支持同时登录多台IP地址不连续的交换机,无需手动逐台登录,提升配置效率;
-
异常处理:捕获登录过程中可能出现的所有异常(网络不通、用户名密码错误,避免脚本崩溃,同时给出清晰的错误提示,方便排查问题;
-
配置复用:脚本可灵活修改配置命令,适配不同的实验需求(如批量配置VLAN、IP地址、静态路由等)。
-
在执行python脚本前,需要再桌面上建立两个txt文件,ip_list(放我们配置的五台交换机的ip地址),cmd.txt(写上命令:display clock)可根据需要修改,我们把交换机SW3(192.168.56.13)的用户名admin的密码改为123,并将SW4(192.168.56.14)的G0/0/1接口断开,用来模拟SSH登录故障
三、Python脚本实现
import paramiko
import time
import getpass
import sys
import socket
import os
from typing import List
def load_file_content(file_path: str, file_type: str) -> List[str]:
if not os.path.exists(file_path):
raise FileNotFoundError(f"{file_type}文件 {file_path} 不存在!")
with open(file_path, 'r', encoding='utf-8') as f:
content = [line.strip() for line in f.readlines() if line.strip()]
if not content:
raise ValueError(f"{file_type}文件 {file_path} 为空,请检查内容!")
return content
def ssh_execute_commands(ip: str, username: str, password: str, commands: List[str]) -> None:
ssh_client = None
try:
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(
hostname=ip,
username=username,
password=password,
look_for_keys=False,
allow_agent=False,
timeout=10
)
print("Successfully connect to", ip)
command_shell = ssh_client.invoke_shell()
command_shell.settimeout(5)
time.sleep(1)
for cmd in commands:
if not cmd.strip():
continue
print(f"向{ip}发送命令: {cmd}")
command_shell.send(f"{cmd}\n")
time.sleep(1.5)
time.sleep(2) # 等待所有命令执行完成
output = command_shell.recv(65535).decode('utf-8', errors='ignore')
print(f"\n{ip} 执行结果:\n{output[:1000]}")
except paramiko.ssh_exception.AuthenticationException:
raise Exception(f"认证失败")
except socket.timeout:
raise Exception(f"连接超时")
except socket.error:
raise Exception(f"网络不可达")
except paramiko.ssh_exception.SSHException:
raise Exception(f"SSH服务未开启或连接被拒绝")
except Exception as e:
raise Exception(f"未知错误: {str(e)}")
finally:
if ssh_client:
ssh_client.close()
print(f"已关闭{ip}的SSH连接")
def main():
if len(sys.argv) != 3:
print("使用方法错误!正确格式:")
print(f"python {sys.argv[0]} <IP列表文件路径> <命令列表文件路径>")
print("示例:python 3.1.py ip_list.txt cmd_list.txt")
sys.exit(1)
ip_file = sys.argv[1]
cmd_file = sys.argv[2]
username = input("请输入登录用户名: ").strip()
if not username:
print("用户名不能为空!")
sys.exit(1)
password = getpass.getpass("请输入登录密码: ").strip()
if not password:
print("密码不能为空!")
sys.exit(1)
try:
ip_list = load_file_content(ip_file, "IP列表")
cmd_list = load_file_content(cmd_file, "命令列表")
print(f"\n加载完成 - IP数量: {len(ip_list)} | 命令数量: {len(cmd_list)}")
except Exception as e:
print(e)
sys.exit(1)
auth_fail_list: List[str] = []
unreachable_list: List[str] = []
error_list: List[str] = []
for ip in ip_list:
print(f"\n{'='*50}")
print(f"开始处理设备: {ip}")
print(f"{'='*50}")
try:
ssh_execute_commands(ip, username, password, cmd_list)
except Exception as e:
error_msg = f"{ip} - {str(e)}"
print(f"{error_msg}")
if "认证失败" in error_msg:
auth_fail_list.append(ip)
elif "超时" in error_msg or "不可达" in error_msg:
unreachable_list.append(ip)
else:
error_list.append(error_msg)
time.sleep(1)
print(f"\n{'='*60}")
print("执行结果汇总:")
print(f"认证失败的设备: {auth_fail_list if auth_fail_list else '无'}")
print(f"网络不可达的设备: {unreachable_list if unreachable_list else '无'}")
print(f"其他错误: {error_list if error_list else '无'}")
print(f"{'='*60}")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n\n用户手动终止程序!")
sys.exit(0)
except Exception as e:
print(f"\n程序异常终止: {str(e)}")
sys.exit(1)
四、实验验证与结果
我们先来看模拟器的云与主机映射通了没

打开PowerShell执行脚本,回显如下图


可见,脚本正常执行,遇到错误后记录错误类型,并继续执行脚本,最终汇总错误
五、常见问题排查与优化建议
5.1 常见问题排查
-
问题1:脚本提示“连接超时”,但ping交换机IP能通? 解决:检查交换机SSH服务是否启用(执行`display ssh server status`查看),或VTY终端是否配置`protocol inbound ssh`。
-
问题2:身份验证失败,但用户名密码正确? 解决:检查交换机AAA用户的`service-type`是否配置为`ssh`,或密码是否为密文配置(脚本中使用明文密码,交换机需配置对应密文)。
-
问题3:脚本执行时“吞指令”,部分配置未生效? 解决:增加`time.sleep()`的延迟时间(如调整为0.5秒),避免命令执行过快,适配ENSP模拟器的响应速度。
-
问题4:地址不连续的交换机无法批量处理? 解决:检查`switch_ips`列表是否正确填写IP地址,无需按顺序排列,脚本会循环逐一处理每一个IP。
六、总结
本文通过Python脚本结合paramiko库,实现了ENSP模拟器中地址不连续交换机的批量SSH登录与配置,核心亮点在于完善的异常处理机制,能够捕获登录过程中的各种常见异常,避免脚本崩溃,同时通过日志记录方便问题排查。
相比于手动逐台登录配置,该脚本大幅提升了工作效率,尤其适合多设备、重复配置的场景;同时脚本结构清晰、注释详细,可根据实际实验或运维需求,灵活修改配置命令和参数,适配不同的交换机型号和配置场景。
后续可根据实际需求,对脚本进行进一步优化(如多线程、配置校验、密码加密等),让批量运维更高效、更安全。如果你的实验过程中遇到其他问题,欢迎在评论区交流讨论~
补充说明
本文实验脚本基于华为交换机编写,若使用其他厂商(如华三、Cisco)的交换机,需修改SSH连接参数和配置命令,核心的批量登录和异常处理逻辑可直接复用;ENSP模拟器中,若交换机无法与Python主机连通,需检查云设备的配置,确保桥接模式正确,IP网段一致。
文章部分内容和思路参考了知乎大神奕心的书《网络工程师的python之路》
=========内容部分来源于网络,如有侵权联系作者========
更多推荐



所有评论(0)