目录
前言
在网络设备数量超过千台甚至万台的大型企业中,难免会遇到某些设备的管理IP地址不通,SSH连接失败的情况,设备数量越多,这种情况的发生概率就越高,在这个时候如果你想用python批量配置所有的设备,就一定要注意这种情况,比如你有几百台设备需要统一更改本地用户名和密码,前100台交换机的连通性应该没啥问题,但是到了101台因为某个网络问题导致管理IP不可达,SSH连不上,此时Python就会返回一个错误(TimeoutError:timed out),如下图所示
如果是由于认证的用户名或者密码错误,python就会返回另外一个错误(paramiko.ssh_exception.AuthenticationException: Authentication failed.)
然后,脚本就会因此停住,如下图所示
如何解决上述两种情况, 如果已经学过Python的都知道,try...except,异常处理,下面我们就用实验来演示异常处理在上述两种情况的应用
1.实验环境
检查一下是否正确安装了下列工具并且保证版本能够正常使用
- python 3.10.x(笔者这里的python是3.10.6)
- Pycharm社区版或者专业版(社区版足矣)
- 华为的ENSP模拟三层交换设备
- 操作系统Windows 10
2.网络拓扑
2.实验目的
使用上述拓扑,将交换机SW1上的用户名python的密码修改,并将SW3的接口down掉
创建一个带有try.....except..异常处理语句的脚本来批量在交换机SW1-SW3上执行display clock命令,让脚本在SW1和SW3分别因为用户名密码不匹配,以及连通性出现故障的情况下,依然可以不受干扰,进而完成SW2的配置
3. 实验准备
(1)首先将SW1的用户名python的密码从python改成123
aaa local-user python password cipher 123
(2)然后将SW3的端口down掉
interface GigabitEthernet0/0/1 shutdown
(3)创建一个名为ip_list.txt和cmd.txt的文本文件,里面包含SW1-SW3的管理IP以及要执行的命令
(4) 最后创建lab.py文件,代码如下
import paramiko import sys import time username = 'python' password = 'python' ip_file = sys.argv[1] cmd_file = sys.argv[2] switch_with_authenication_issue = [] switch_not_reachable = [] unreachable = open("unreachable.txt","w") Authentication_fail = open("fail.txt",'w') ip_list = open("ip_list.txt","r") for line in ip_list.readlines(): try: ip = line.strip() client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(hostname=ip, username=username, password=password,look_for_keys=False) print("成功登录到{}".format(ip)) command = client.invoke_shell() cmdlist = open('cmd.txt','r') cmdlist.seek(0) for line in cmdlist.readlines(): command.send(line + "\n") time.sleep(2) cmdlist.close() output = command.recv(65535) print(output.decode('ascii')) except paramiko.ssh_exception.AuthenticationException: print("User authentication failed for " + ip + ".") switch_with_authenication_issue.append(ip) except TimeoutError: print(ip + " " + "is not reachable") switch_not_reachable.append(ip) ip_list.close() client.close() print('\nUser authentication failed for below switches: ') for i in switch_with_authenication_issue: print(i) Authentication_fail.write(i) print('\nBelow switches are not reachable: ') for i in switch_not_reachable: unreachable.write(i) print(i) unreachable.close() Authentication_fail.close()
4.代码分段讲解如下
如果运行环境是linux环境的话,网络不可达的报错是socket.error,就必须导入socket模块,这里笔者的环境是win,就不再做linux环境下的Python脚本的演示
(1)首先还是老样子,引入我们需要的模块
import paramiko import sys import time
(2)定义用户名和密码,以及使用sys为用户提供访问Python解释器的接口,用来访问Python的使用和维护的变量,实现从程序外部向程序传递参数
sys.argv[0] #表示程序自身 sys.argv[1] #表示程序的第一个参数 sys.argv[2] #表示程序的第二个参数我们在命令上调用py lab.py ip_list.txt cmd.txt,sys.argv[0]就表示我们脚本lab.py,sys.argv[1]表示ip_list.txt,sys.argv[2]表示cmd.txtusername = 'python' password = 'python' ip_file = sys.argv[1] cmd_file = sys.argv[2] #"argv"即"argument value"的简写,是一个列表对象,其中存储的是在命令行调用Python脚本是提供的"命令行参数"。
(3)创建两个空列表,分别命名为switch_with_authenication_issue 和 switch_not_reachable以及创建连个TXT,用来存储以上出现异常的交换机
他们的作用是用来存储那些是由于网络原因或者认证问题无法登录交换机IP的
switch_with_authenication_issue = [] switch_not_reachable = []
(4)在for循环下使用try......except...异常处理语句,当SSH登录交换机时,如果用户名和密码不正确,我们就用 except paramiko.ssh_exception.AuthenticationException:来应对该异常,然后打印出用户失败的IP或者将其存储到TXT文件里面,这里面笔者都演示了两种方法,然后将出现该异常的交换机的管理地址用列表的append()方法放入switch_with_authenication_issue列表中,同理我们用TimeoutError来应对网络不可达的情况,然后将出现该异常的交换机地址用列表的append()方法放入switch_not_reachable中,并打印出该异常交换机的管理IP或者使用write()方法将其写入到TXT文件里
注意:如果要时存在多个异常的IP,如果要用write方法,要把文件的模式改成w和a模式,a表示追加,w表示写,如果已经有IP存在TXT文件,不加a的话,里面原来的内容将被覆盖,或者使用writelines直接将所有的都写进去,根据个人喜好来,笔者这里就不演示了,具体教程看这里
Python File(文件) 方法 | 菜鸟教程 (runoob.com)
ip_list = open("ip_list.txt","r") for line in ip_list.readlines(): try: ip = line.strip() client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(hostname=ip, username=username, password=password,look_for_keys=False) print("成功登录到{}".format(ip)) command = client.invoke_shell() cmdlist = open('cmd.txt','r') cmdlist.seek(0) #设置文件当前为开头,将光标移动到开头,从头开始读文件的每一行 for line in cmdlist.readlines(): command.send(line + "\n") time.sleep(2) cmdlist.close() output = command.recv(65535) print(output.decode('ascii')) except paramiko.ssh_exception.AuthenticationException: print("User authentication failed for " + ip + ".") switch_with_authenication_issue.append(ip) except TimeoutError: print(ip + " " + "is not reachable") switch_not_reachable.append(ip) ip_list.close() client.close()
(5)最后使用for循环,打印出switch_with_authenication_issue和switch_not_reachable两个列表中的元素,这样就能清楚的看到那些交换机用户名和密码验证失败,那些交换机的管理IP地址不可达,用writelines的时候要加换行符,不然TXT文件里的格式不好看,如下图所示
print('\nUser authentication failed for below switches: ') for i in switch_with_authenication_issue: print(i) Authentication_fail.writelines(i + '\n') print('\nBelow switches are not reachable: ') for i in switch_not_reachable: unreachable.writelines(i + '\n') print(i) unreachable.close() Authentication_fail.close()
这是加了换行符的
不加换行符
(6)验证代码运行和生成的文件
至此,实验完成,有哪些地方有错误可以私聊笔者