關於使用python批量操作網絡設備,這里本人目前只接觸了兩個模塊,netmiko和pratmiko,后面的腳本也都將基於這兩個模塊。
一、netmiko模塊
1、使用netmiko模塊連接操作設備
import netmiko #導入netmiko模塊
import time #導入time模塊
#使用with語句打開用於ssh連接所需要的相關信息(用戶名,密碼,ip地址,需要配置的命令),這個打開了兩個文件用戶信息文件,命令文件,分別命名為devices_file,cmd_file
with open("ip_user_pass.txt", "r") as devices_file, open("cmdlist.txt", "r") as cmd_file: #將用戶信息文件按行讀取賦值給devices
devices = devices_file.readlines() #將命令文件按行讀取賦值給cmdlist
cmdlist = cmd_file.readlines() #使用循環將用戶名,密碼,IP地址,分別賦值給username,password,ip_address變量,並依次登陸
for line in devices: line = line.strip("\n") ip_address = line.split(",")[0] #split() 通過指定分隔符對字符串進行切片,如果參數 num 有指定值,則分隔 num+1 個子字符串
username = line.split(",")[1] password = line.split(",")[2] #創建一個名為SW2的字典,該字典包含“device_type”“ip”“username”和“password”4個必選的鍵,如果設備類型是netmiko不支持的類型,不清楚還能不能連接
SW2 = { 'device_type': 'huawei', 'ip': ip_address, 'username': username, 'password': password, } connect = netmiko.ConnectHandler(**SW2) #函數ConnectHandler()。該函數用來實現SSH登錄網絡設備,是Netmiko最重要的函數。
print("Successfully connect to" + SW2['ip']) #config_commands = ['dis arp']
#output = connect.send_config_set(config_commands)
#rint(output)
#使用循環將cmdlist中的命令依次輸入
for cmd in cmdlist: output2 = connect.send_config_set(cmd) #send_config_set()則可向設備一次輸入多個命令
print(output2) time.sleep(1) print("*" * 50 + "分割線" + "*" * 50) #result = connect.send_command('dis int LoopBack 0')
#print(result)
腳本運行結果如下:
2、ssh_netmiko_多線程
使用netmiko實現多線程操作網絡設備
#coding=utf-8 import threading #Python 3已經內置了threading模塊來實現多線程,這里引入 from queue import Queue #多線程中需要用的隊列,這里引入,多線程中需要用的隊列,這里引入,通過隊列傳遞數據,安全,不會造成多個線程訪問時混亂
import netmiko import time #定義連接函數,使用netmiko連接設備,並輸入預定義命令 def ssh_session(ip, username, password,cmdlist, output_q): SW2 = { 'device_type': 'huawei', 'ip': ip_address, 'username': username, 'password': password, } connect = netmiko.ConnectHandler(**SW2) print("Successfully connect to" + SW2['ip']) ''' config_commands = ['dis arp', 'dis ip routing-table', 'dis int brief'] output = connect.send_config_set(config_commands) print(output) print("*" * 50 + "分割線" + "*" * 50) ''' for cmd in cmdlist: output = connect.send_config_set(cmd) print(output) time.sleep(1) print("*" * 50 + "分割線" + "*" * 50) #result = connect.send_command('dis int LoopBack 0') #print(result) print("程序於 {} 開始執行\n".format(time.strftime("%X"))) threads = [] with open("ip_user_pass.txt", "r") as devices_file, open("cmdlist.txt", "r") as cmd_file: devices = devices_file.readlines() cmdlist = cmd_file.readlines() for line in devices: line = line.strip("\n") ip_address = line.split(",")[0] #split() 通過指定分隔符對字符串進行切片,如果參數 num 有指定值,則分隔 num+1 個子字符串 username = line.split(",")[1] password = line.split(",")[2] #使用threading的Thread()函數為ssh_session函數創建一個線程並將它賦值給變量t,注意Thread()函數的target參數對應的是函數名稱(即ssh_session) #args對應的是該ssh_session函數的參數 t = threading.Thread(target=ssh_session, args=(ip_address, username, password, cmdlist, Queue())) t.start() threads.append(t) for i in threads: i.join() #threading的join()方法的作用是強制阻塞調用它的線程,直到該線程運行完畢或者終止(類似單線程同步) print("程序於 {} 執行結束\n".format(time.strftime("%X")))
腳本缺少錯誤控制加入try語句,可以更好的應用腳本,不會因為地址和用戶名密碼錯誤導致腳本中斷,另外關於腳本里的使用了隊列實現線程控制,但是為什么要寫成這個形式
t = threading.Thread(target=ssh_session, args=(ip_address, username, password, cmdlist, Queue())),目前我還不太了解。希望知道原理的大大能告訴我一下~
二、prarmiko模塊
1、使用prarmiko模塊連接網絡設備操作(連接協議ssh)
''' 需在命令行運行程序,並給四個文件參數,存放ip的文件在前,存放命令的文件在后,例如:python lab3_1.py ip.txt cmdlist.txt username.txt password.txt ''' import paramiko import time import getpass import sys import socket #username = input("username:") #password = getpass.getpass("password:") ip_file = sys.argv[1] #sys.argv[]就是一個從程序外部獲取參數的橋梁,外部取得的參數可以是多個,所以獲得的是一個列表(list),其第一個元素是程序本身,隨后才依次是外部給予的參數, cmd_file = sys.argv[2] #這里使用sys.argv(),即將保存的ip和命令的文件作為參數賦值給變量 user_file = sys.argv[3] pass_file = sys.argv[4] switch_with_authentication_issue = [] #認證失敗的列表,用於存放用戶認證失敗的IP地址 switch_not_reachable = [] #連接失敗的列表,用於存放連接失敗的ip地址 #打開文件用戶信息文件,IP地址文件 iplist = open(ip_file, "r") userlist = open(user_file, "r") passlist = open(pass_file, "r") #使用循環按行讀取,文件內容,這個用zip() 函數將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,然后返回由這些元組組成的對象 #例如: 192.168.1.1 admin 123 for line1, line2, line3 in zip(iplist.readlines(), userlist.readlines(), passlist.readlines()): try: ip = line1.strip() username = line2.strip() password = line3.strip() ssh_client = paramiko.SSHClient() #調用paramiko的SSHClient方法連接網絡設備,及本地設備為客戶端 ''' 默認情況下,Paramiko會拒絕任何未知的SSH公鑰(publickey),這里我們需要使用ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 來讓Paramiko接受SSH服務端(也就是SW3)提供的公鑰,這是任何時候使用Paramiko都要用到的標准配置。 ''' ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh_client.connect(hostname=ip, username=username, password=password) #調用connect()方法,輸入連接設備所需的ip,用戶名,密碼 print("登錄成功", ip) command = ssh_client.invoke_shell() #調用Paramiko.SSHClient()的invoke_shell()方法來喚醒shell cmdlist = open(cmd_file, "r") #讀入命令文件 cmdlist.seek(0) #seek() 方法用於移動文件讀取指針到指定位置,參數為0代表從文件開頭開始算起。 for line in cmdlist.readlines(): command.send(line + "\n") time.sleep(5) cmdlist.close() output = command.recv(65535) print(output.decode("ascii")) except paramiko.ssh_exception.AuthenticationException: print("用戶認證失敗:" + ip) switch_with_authentication_issue.append(ip) except socket.error: print(ip + "連接失敗") switch_not_reachable.append(ip) iplist.close() userlist.close() passlist.close() ssh_client.close print("*" * 50 + "分割線" + "*" * 50) print("\n用戶認證失敗的交換機:\n") for i in switch_with_authentication_issue: print(i) print("\n網絡連接失敗交換機:\n") for i in switch_not_reachable: print(i)
三、配置文件備份
1、使用netmiko備份,用於備份netmiko支持的設備,使用h3c設備測試此腳本,備份失敗(可能是netmiko中沒有h3c的相關函數)
import netmiko import time with open("devices.txt") as devices_file: devices = devices_file.readlines() for line in devices: line = line.strip("\n") ipaddr = line.split(",")[0] #split() 通過指定分隔符對字符串進行切片,如果參數 num 有指定值,則分隔 num+1 個子字符串 username = line.split(",")[1] password = line.split(",")[2] vendor = line.split(",")[3] SW2 = { 'device_type': vendor, 'ip': ipaddr, 'username': username, 'password': password, } now = time.strftime("%Y-%m-%d", time.localtime()) connect = netmiko.ConnectHandler(**SW2) print("Successfully connect to" + SW2['ip']) backup_cfg = connect.send_command("dis cur") #將命令內容賦值給變量 print(backup_cfg) #將變量的值寫入文件,文件命名按時間划分 with open( "C:\\ftp\\交換機_" + str(now) + "_{}.txt".format(ipaddr), "w") as f: f.write(backup_cfg)
2、使用prarmiko,基於tftp備份配置文件
首先要搭建一個tftp服務器,使用tftp相關軟件即可
其次運行腳本
import paramiko import time with open("ip_user_pass.txt") as devices_file: devices = devices_file.readlines() for line in devices: line = line.strip("\n") ip_address = line.split(",")[0] #split() 通過指定分隔符對字符串進行切片,如果參數 num 有指定值,則分隔 num+1 個子字符串 username = line.split(",")[1] password = line.split(",")[2] now = time.strftime("%Y-%m-%d", time.localtime()) ssh_client = paramiko.SSHClient() ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh_client.connect(hostname=ip_address, username=username, password=password) print("登陸成功:",ip_address) command = ssh_client.invoke_shell() command.send("copy startup.cfg {}_{}.cfg\n".format(now,ip_address)) command.send("y\n") command.send("tftp 192.168.134.222 put {}_{}.cfg\n".format(now,ip_address)) time.sleep(15) command.send("delete {}_{}.cfg\n".format(now,ip_address)) command.send("y\n") time.sleep(5) output = command.recv(65535) print(output.decode("ascii")) ssh_client.close