华为交换机配置自动化备份实践 华为交换机备份配置)
在上一篇文章中,我實踐了通過Python的paramiko模塊來SSH登錄到華為交換機上批量備份配置文件到FTP服務器上。最后總結存在兩個問題,一個是在腳本運行過程中,如果中間某臺設備因用戶名密碼錯誤或者網絡不可達的情況,會導致腳本中斷運行無法繼續執行下去,后面設備的備份也無法完成。第二個就是由于python默認是單線程串行執行的,在設備量大的時候效率可能不高,腳本需要運行的時間比較長。
本篇文章將會通過try...except來實現異常處理,以及通過threading模塊來解決多線程問題,并發執行多臺設備同時進行備份操作。
本實驗通過學習@弈心大佬的《網絡工程師的Python之路》后結合自己的理解和思路形成。
實驗環境及拓撲仍然跟上次一樣,python實驗平臺與5臺交換機橋接在一起。
異常處理try...except
異常是一個事件,在程序執行過程中python無法正常處理的程序發生的話,就會影響程序的正常執行。Python可以通過try...except語句來檢測try語句塊中的錯誤,并且讓except語句來捕獲異常信息并進行處理。
首先基于上一次的實驗的基礎上,加入異常處理的機制,以下是加入異常處理機制后完整的代碼。
下面我們來對代碼進行分析。
第一部分
for line in f.readlines():
try:
line_s = line.split( )
device_ip = line_s[0]
device_name = line_s[1]
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 + ' 網絡不可達..')
device_not_reachable_list.append(device_ip)主代碼跟上一次實驗是一樣的,只是在主代碼前面加入try,并在主代碼后加入except捕獲具體的異常信息。如果try后的語句執行時發生異常,python就會跳到except來判斷異常信息,并執行響應動作。如果try后的語句執行正常,則會跳過except,就跟if...else條件判斷語句是一個意思。
主代碼跟上一次實驗是一樣的,只是在主代碼前面加入try,并在主代碼后加入except捕獲具體的異常信息。如果try后的語句執行時發生異常,python就會跳到except來判斷異常信息,并執行相應的動作。如果try后的語句執行正常,則會跳過except,就跟if...else條件判斷語句是一個意思。
網絡設備登錄異常通常有2個場景,一個就是用戶名密碼錯誤,即認證失敗無法登錄上設備,第二個就是這臺網絡設備斷網了無法連接上。
通過paramiko登錄設備認證失敗的話,python會拋出異常信息 paramiko.ssh_exception.AuthenticationException,因此我們通過except來捕獲這個異常報錯信息來執行下面的動作,這里我們會先打印一個信息提示這個IP認證失敗的原因,并且將該異常設備的IP地址添加進先前定義好的空列表device_authentication_failed_list里。網絡不可達的異常需要引入socket模塊來處理,當設備連接不上時會報socket.error,同樣的把這個異常情況打印出來并放到定義好的空列表device_not_reachable_list里。
第二部分
print('\n以下設備認證失敗無法登錄: ')
if device_authentication_failed_list == []: #判斷是否為空列表
print('無')
else:
for i in device_authentication_failed_list:
print(i)
print('\n以下設備網絡不可達: ')
if device_not_reachable_list == []:
print('無')
else:
for i in device_not_reachable_list:
print(i)
最后,當程序執行完把所有出現登錄異常的設備的打印出來,后期人工再做后續處理。判斷如果列表為空,則打印“無”,否則非空則分別打印出列表里的異常設備IP。
異常處理實驗驗證
把SW2的登錄密碼修改為Cisco@123(模擬認證失?。裇W4連HUB的接口G0/0/1 shutdown掉(模擬網絡不可達),再運行腳本。
可以看到,在腳本執行過程中對于無法登錄的設備會打印出異常信息,并繼續執行下一臺設備的備份操作而不會中途中斷。在所有設備備份執行完之后,會統計出所有異常設備的IP并打印出來。
多線程 threading
Python默認是單線程的,在執行備份腳本的時候通過輸出可以看到是在備份完一臺設備后再備份另外一臺這樣串行執行的。由于本次實驗總共就5臺設備,所以整個備份時間都可以接受,那如果現網中有幾十上百臺設備的話,單線程執行的過程會是比較慢的,下面就介紹通過python自帶的threading模塊來實現多線程并發執行多臺設備同時備份,加快程序執行效率。據說有更好用的多線程模塊,后面我也會繼續研究學習一下。
本次實驗我會對代碼稍微改造一下,將SSH登錄及命令執行封裝成函數ssh_f,然后用后面代碼調用ssh_f函數。全部代碼如下。
代碼解析
第一部分
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 + ' 網絡不可達')
device_not_reachable_list.append(ip)
ssh_client.close()
此部分只是把先前的代碼封裝成了函數,定義了函數名為ssh_f,函數內的代碼跟先前是一樣的,只是把ssh登錄跟下發命令的代碼單獨抽取了出來放到函數里,這樣能夠方便后面代碼的調用。并對ssh_f函數定義了這幾個參數,ip, username, password, device_name, date,后面調用時會傳參進去。
第二部分
username = 'python'
password = 'Python@123'
date = time.strftime('%Y-%m-%d')
threads = [10]
device_authentication_failed_list = []
device_not_reachable_list = []
print('開始執行備份操作...')
f = open('devices_list.txt', 'r')
for line in f.readlines():
line_s = line.split( )
ip_address = line_s[0]
device_name = line_s[1]
#使用threading的Thread()函數為ssh_2函數創建一個線程并將它賦值給變量a,注意Thread()函數的target參數對應的是函數名稱(即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) #先等待所有操作執行完,再打印異常列表
print('\n以下設備認證失敗無法登錄: ')
if device_authentication_failed_list == []: # 判斷是否為空列表
print('無')
else:
for i in device_authentication_failed_list:
print(i)
print('\n以下設備網絡不可達: ')
if device_not_reachable_list == []:
print('無')
else:
for i in device_not_reachable_list:
print(i)
接下來的代碼其實跟之前的主代碼基本差不多,不再一一解釋。增加的點就是在for循環里增加了threading的代碼,并且在threading里調用剛才定義的ssh_f函數用于ssh連接及命令執行。
使用threading的Thread()函數為ssh_2函數創建一個線程并將它賦值給變量a,Thread()函數的target參數對應的是函數名稱ssh_2,args對應的是該ssh_f函數的參數,相關參數都已經定義并傳參進來。
然后a.start() 啟動線程。使用threading多線程,這樣下一個操作就不需要等上一個操作執行完后再開始執行,實現了并行執行。
實驗驗證
下面我們就對這個腳本運行一下,再來看看這5臺設備的備份效果。特意制作了以下的GIF動圖,可以看到5臺設備的備份過程基本上是同時連接上,并且是幾乎同時完成的,不再是前面實驗一樣先完成一臺后再執行下一臺,這樣,這個腳本的執行效率就會大大的提升,如果設備多的話將會腳本運行的效率就會有量級的提升。
可以看到服務器文件目錄里已經能夠正常獲取到5臺交換機的配置文件。
總結
通過以上兩個實驗案例,通過異常處理及多線程,就可以優化上一個實驗遺留下來的2個問題了。以上的實踐尤其是多線程并發處理,肯定還有很多方式可以實現,接下來我也會繼續探索更多Netdevops的內容。由于目前還處于小白的階段,以上編寫的代碼和解讀肯定還有很多不足和理解不夠深入之處,如有任何錯誤的地方還請各位朋友指出,共同學習!
總結
以上是生活随笔為你收集整理的华为交换机配置自动化备份实践 华为交换机备份配置)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Request.Form的用法
- 下一篇: love的网名135个