「网络自动化运维」华为交换机配置自动化备份实践(优化篇)
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在上一篇<span style="color: black;">文案</span>中<a style="color: black;">「网络自动化运维」华为交换机配置自动化备份实践(<span style="color: black;">基本</span>篇)</a>,我实践了<span style="color: black;">经过</span>Python的paramiko模块来SSH登录到华为交换机上批量备份配置文件到FTP服务器上。最后总结存在两个问题,一个是在脚本运行过程中,<span style="color: black;">倘若</span>中间某台设备因用户名<span style="color: black;">秘码</span>错误<span style="color: black;">或</span>网络不<span style="color: black;">达到</span>的<span style="color: black;">状况</span>,会<span style="color: black;">引起</span>脚本中断运行<span style="color: black;">没法</span>继续执行下去,后面设备的备份<span style="color: black;">亦</span><span style="color: black;">没法</span>完成。第二个<span style="color: black;">便是</span><span style="color: black;">因为</span>python默认是单线程串行执行的,在设备量大的时候效率可能不高,脚本需要运行的时间比较长。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">本篇<span style="color: black;">文案</span>将会<span style="color: black;">经过</span>try...except来实现<span style="color: black;">反常</span>处理,以及<span style="color: black;">经过</span>threading模块来<span style="color: black;">处理</span>多线程问题,并发执行多台设备<span style="color: black;">同期</span>进行备份操作。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">本实验<span style="color: black;">经过</span>学习<a style="color: black;">@</a>弈心大佬的《网络工程师的Python之路》后结合自己的理解和思路形成。</span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">实验环境及拓扑仍然跟上次<span style="color: black;">同样</span>,python实验平台与5台交换机桥接在<span style="color: black;">一块</span>。</p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p26-sign.toutiaoimg.com/pgc-image/bdf3079672c149ffbcc40844f5b64683~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1725634599&x-signature=w0VuAEw8cHYemcE5sIaucOwYcHE%3D" style="width: 50%; margin-bottom: 20px;"></div>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">反常</span>处理try...except</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">反常</span>是一个事件,在程序执行过程中python<span style="color: black;">没法</span>正常处理的程序<span style="color: black;">出现</span>的话,就会影响程序的正常执行。Python<span style="color: black;">能够</span><span style="color: black;">经过</span>try...except语句来检测try语句块中的错误,并且让except语句来<span style="color: black;">捕捉</span><span style="color: black;">反常</span>信息并进行处理。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">首要</span>基于上一次的实验的<span style="color: black;">基本</span>上,加入<span style="color: black;">反常</span>处理的机制,以下是加入<span style="color: black;">反常</span>处理机制后完整的代码。</p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/8af7fb367b6f4b00a072bdd18dc5fff7~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1725634599&x-signature=hYeJAxNw5%2FI1Did4NZ8JPs3K3I8%3D" style="width: 50%; margin-bottom: 20px;"></div>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">下面<span style="color: black;">咱们</span>来对代码进行分析。</strong></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第1</span>部分</p>for line in f.readlines():
try:
line_s = line.split( )
device_ip = line_s
device_name = line_s
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=device_ip, username=username, password=password)
print(成功连接上 , device_ip)
command = ssh_client.invoke_shell()
command.send(save\n)
command.send(y\n)
time.sleep(1)
command.send(ftp 192.168.134.1\n)
command.send(ftpuser\n)
command.send(ftpuser\n)
command.send(put vrpcfg.zip + date + _ + device_name + _vrpcfg.zip\n)
command.send(bye\n)
time.sleep(1)
output = command.recv(65535)
print(output.decode(UTF-8))
except paramiko.ssh_exception.AuthenticationException:
print(device_ip + 用户认证失败..)
device_authentication_failed_list.append(device_ip)
except socket.error:
print(device_ip + 网络不<span style="color: black;">达到</span>..)
device_not_reachable_list.append(device_ip)主代码跟上一次实验是<span style="color: black;">同样</span>的,只是在主代码前面加入try,并在主代码后加入except<span style="color: black;">捕捉</span><span style="color: black;">详细</span>的<span style="color: black;">反常</span>信息。<span style="color: black;">倘若</span>try后的语句执行时<span style="color: black;">出现</span><span style="color: black;">反常</span>,python就会跳到except来判断<span style="color: black;">反常</span>信息,并执行响应动作。<span style="color: black;">倘若</span>try后的语句执行正常,则会跳过except,就跟if...else<span style="color: black;">要求</span>判断语句是一个意思。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">主代码跟上一次实验是<span style="color: black;">同样</span>的,只是在主代码前面加入try,并在主代码后加入except<span style="color: black;">捕捉</span><span style="color: black;">详细</span>的<span style="color: black;">反常</span>信息。<span style="color: black;">倘若</span>try后的语句执行时<span style="color: black;">出现</span><span style="color: black;">反常</span>,python就会跳到except来判断<span style="color: black;">反常</span>信息,并执行相应的动作。<span style="color: black;">倘若</span>try后的语句执行正常,则会跳过except,就跟if...else<span style="color: black;">要求</span>判断语句是一个意思。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">网络设备登录<span style="color: black;">反常</span><span style="color: black;">一般</span>有2个场景,一个<span style="color: black;">便是</span>用户名<span style="color: black;">秘码</span>错误,即认证失败<span style="color: black;">没法</span>登录上设备,第二个<span style="color: black;">便是</span>这台网络设备断网了<span style="color: black;">没法</span>连接上。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">经过</span>paramiko登录设备认证失败的话,python会抛出<span style="color: black;">反常</span>信息 </p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">paramiko.ssh_exception.AuthenticationException,<span style="color: black;">因此呢</span><span style="color: black;">咱们</span><span style="color: black;">经过</span>except来<span style="color: black;">捕捉</span>这个<span style="color: black;">反常</span>报错信息来执行下面的动作,<span style="color: black;">这儿</span><span style="color: black;">咱们</span>会先打印一个信息提示这个IP认证失败的<span style="color: black;">原由</span>,并且将该<span style="color: black;">反常</span>设备的IP<span style="color: black;">位置</span>添加进先前定义好的空列表</p>device_authentication_failed_list里。网络不<span style="color: black;">达到</span>的<span style="color: black;">反常</span>需要引入socket模块来处理,当设备连接不上时会报socket.error,<span style="color: black;">一样</span>的把这个<span style="color: black;">反常</span><span style="color: black;">状况</span>打印出来并放到定义好的空列表device_not_reachable_list里。
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">第二部分</p>print(\n以下设备认证失败<span style="color: black;">没法</span>登录: )
if device_authentication_failed_list == []: #判断<span style="color: black;">是不是</span>为空列表
print(无)
else:
for i in device_authentication_failed_list:
print(i)
print(\n以下设备网络不<span style="color: black;">达到</span>: )
if device_not_reachable_list == []:
print(无)
else:
for i in device_not_reachable_list:
print(i)<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">最后,当程序执行完把所有<span style="color: black;">显现</span>登录<span style="color: black;">反常</span>的设备的打印出来,后期人工再做后续处理。判断<span style="color: black;">倘若</span>列表为空,则打印“无”,否则非空则分别打印出列表里的<span style="color: black;">反常</span>设备IP。</p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">反常</span>处理实验验证</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">把SW2的登录<span style="color: black;">秘码</span>修改为Cisco@123(模拟认证失败),把SW4连HUB的接口G0/0/1 shutdown掉(模拟网络不<span style="color: black;">达到</span>),再运行脚本。</p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/2609816fff564b58aeddb8ee5c5a3cd0~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1725634599&x-signature=qjUcbBfIMM58eyPBstrm5Nyhn5E%3D" style="width: 50%; margin-bottom: 20px;"></div>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/0a1eddaeb540421a88648b777ed1b915~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1725634599&x-signature=J9u3A1dNygsNgEod1WmgNFB8C0k%3D" style="width: 50%; margin-bottom: 20px;"></div>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/90bbb114dd5d491fa94a282bd885c403~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1725634599&x-signature=3J3bMw7a0EZRM52XhdxleQWfJQI%3D" style="width: 50%; margin-bottom: 20px;"></div>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">能够</span>看到,在脚本执行过程中<span style="color: black;">针对</span><span style="color: black;">没法</span>登录的设备会打印出<span style="color: black;">反常</span>信息,并继续执行下一台设备的备份操作而不会<span style="color: black;">半途</span>中断。在所有设备备份执行完之后,会统计出所有<span style="color: black;">反常</span>设备的IP并打印出来。</p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">多线程 threading</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Python默认是单线程的,在执行备份脚本的时候<span style="color: black;">经过</span>输出<span style="color: black;">能够</span>看到是在备份完一台设备后再备份<span style="color: black;">另一</span>一台<span style="color: black;">这般</span>串行执行的。<span style="color: black;">因为</span><span style="color: black;">这次</span>实验总共就5台设备,<span style="color: black;">因此</span><span style="color: black;">全部</span>备份时间都<span style="color: black;">能够</span>接受,那<span style="color: black;">倘若</span>现网中有几十上百台设备的话,单线程执行的过程会是比较慢的,下面就介绍<span style="color: black;">经过</span>python自带的threading模块来实现多线程并发执行多台设备<span style="color: black;">同期</span>备份,加快程序执行效率。<span style="color: black;">据述</span>有更好用的多线程模块,后面我<span style="color: black;">亦</span>会继续<span style="color: black;">科研</span>学习一下。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">这次</span>实验我会对代码稍微改造一下,将SSH登录及命令执行封装成函数ssh_f,<span style="color: black;">而后</span>用后面代码调用ssh_f函数。全部代码如下。</p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/1fb2b4df1f1645d89e807e8bd2214470~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1725634599&x-signature=f5h2%2BRH%2Fj27M2JSrf3jd4kH2jMw%3D" style="width: 50%; margin-bottom: 20px;"></div>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/d48278a4911547fa81e0cbc22f06b4b4~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1725634599&x-signature=PlGJNi1Tttjn%2Bo7q55qkNeRhJMU%3D" style="width: 50%; margin-bottom: 20px;"></div>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">代码解析</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">第1</span>部分</p>def ssh_f(ip, username, password, device_name, date): #封装成函数ssh_f
try:
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=ip, username=username, password=password)
print(成功连接上: , ip)
time.sleep(2)
command = ssh_client.invoke_shell()
command.send(save\n)
command.send(y\n)
time.sleep(1)
command.send(ftp 192.168.134.1\n)
command.send(ftpuser\n)
command.send(ftpuser\n)
command.send(put vrpcfg.zip + date + _ + device_name + _vrpcfg.zip\n)
command.send(bye\n)
time.sleep(1)
print(已完成备份... , ip)
except paramiko.ssh_exception.AuthenticationException:
print(用户认证失败 + ip + .)
device_authentication_failed_list.append(ip)
except socket.error:
print(ip + 网络不<span style="color: black;">达到</span>)
device_not_reachable_list.append(ip)
ssh_client.close()<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">此部分只是把先前的代码封装<span style="color: black;">成为了</span>函数,定义了函数名为ssh_f,函数内的代码跟先前是<span style="color: black;">同样</span>的,只是把ssh登录跟下发命令的代码单独抽取了出来放到函数里,<span style="color: black;">这般</span>能够方便后面代码的调用。并对ssh_f函数定义了这几个参数,ip, username, password, device_name, date,后面调用时会传参进去。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">第二部分</p>username = python
password = Python@123
date = time.strftime(%Y-%m-%d)
threads =
device_authentication_failed_list = []
device_not_reachable_list = []
print(<span style="color: black;">起始</span>执行备份操作...)
f = open(devices_list.txt, r)
for line in f.readlines():
line_s = line.split( )
ip_address = line_s
device_name = line_s
#<span style="color: black;">运用</span>threading的Thread()函数为ssh_2函数创建一个线程并将它赋值给变量a,<span style="color: black;">重视</span>Thread()函数的target参数对应的是函数名<span style="color: black;">叫作</span>(即ssh_2)
#args对应的是该ssh_f函数的参数
a = threading.Thread(target=ssh_f, args=(ip_address, username, password, device_name, date))
a.start()
f.close()
time.sleep(5) #先等待所有操作执行完,再打印<span style="color: black;">反常</span>列表
print(\n以下设备认证失败<span style="color: black;">没法</span>登录: )
if device_authentication_failed_list == []: # 判断<span style="color: black;">是不是</span>为空列表
print(无)
else:
for i in device_authentication_failed_list:
print(i)
print(\n以下设备网络不<span style="color: black;">达到</span>: )
if device_not_reachable_list == []:
print(无)
else:
for i in device_not_reachable_list:
print(i)<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">接下来的代码其实跟之前的主代码基本差不多,<span style="color: black;">再也不</span>一一解释。<span style="color: black;">增多</span>的点<span style="color: black;">便是</span>在for循环里<span style="color: black;">增多</span>了threading的代码,并且在threading里调用刚才定义的ssh_f函数用于ssh连接及命令执行。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">运用</span>threading的Thread()函数为ssh_2函数创建一个线程并将它赋值给变量a,Thread()函数的target参数对应的是函数名<span style="color: black;">叫作</span>ssh_2,args对应的是该ssh_f函数的参数,<span style="color: black;">关联</span>参数都<span style="color: black;">已然</span>定义并传参进来。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;"><span style="color: black;">而后</span>a.start() <span style="color: black;">起步</span>线程。<span style="color: black;">运用</span>threading多线程,<span style="color: black;">这般</span>下一个操作就不需要等上一个操作执行完后再<span style="color: black;">起始</span>执行,实现了并行执行。</span></p>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">实验验证</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">下面<span style="color: black;">咱们</span>就对这个脚本运行一下,再来<span style="color: black;">瞧瞧</span>这5台设备的备份效果。特意制作了以下的GIF动图,<span style="color: black;">能够</span>看到5台设备的备份过程基本上是<span style="color: black;">同期</span>连接上,并且是几乎<span style="color: black;">同期</span>完成的,<span style="color: black;">再也不</span>是前面实验<span style="color: black;">同样</span>先完成一台后再执行下一台,<span style="color: black;">这般</span>,这个脚本的执行效率就会大大的<span style="color: black;">提高</span>,<span style="color: black;">倘若</span>设备多的话将会脚本运行的效率就会有量级的<span style="color: black;">提高</span>。</p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p3-sign.toutiaoimg.com/pgc-image/cb1245daf8da450bab230fe3cc210294~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1725634599&x-signature=gnCI3TENXKIrRDbeCuQAHRwRSh4%3D" style="width: 50%; margin-bottom: 20px;"></div>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">能够</span>看到服务器文件目录里<span style="color: black;">已然</span>能够正常获取到5台交换机的配置文件。</p>
<div style="color: black; text-align: left; margin-bottom: 10px;"><img src="https://p6-sign.toutiaoimg.com/pgc-image/4eeafb5d8d6c4ca18ef9ee7fd46d91fc~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1725634599&x-signature=l28%2BjwU2YTMi05Y9wzV6yjrBBG0%3D" style="width: 50%; margin-bottom: 20px;"></div>
<h1 style="color: black; text-align: left; margin-bottom: 10px;">总结</h1>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">经过</span>以上两个实验案例,<span style="color: black;">经过</span><span style="color: black;">反常</span>处理及多线程,就<span style="color: black;">能够</span>优化上一个实验遗留下来的2个问题了。以上的实践尤其是多线程并发处理,肯定还有<span style="color: black;">非常多</span>方式<span style="color: black;">能够</span>实现,接下来我<span style="color: black;">亦</span>会继续探索<span style="color: black;">更加多</span>Netdevops的内容。<span style="color: black;">因为</span><span style="color: black;">日前</span>还<span style="color: black;">处在</span>小白的<span style="color: black;">周期</span>,以上编写的代码和<span style="color: black;">诠释</span>肯定还有<span style="color: black;">非常多</span>不足和理解<span style="color: black;">不足</span>深入之处,如有任何错误的<span style="color: black;">地区</span>还请各位<span style="color: black;">伴侣</span>指出,<span style="color: black;">一起</span>学习!</p>
外链论坛的成功举办,是与各位领导、同仁们的关怀和支持分不开的。在此,我谨代表公司向关心和支持论坛的各界人士表示最衷心的感谢! 感谢楼主分享,祝愿外链论坛越办越好! 外贸论坛是我们的,责任是我们的,荣誉是我们的,成就是我们的,辉煌是我们的。
页:
[1]