Python 备份网络设备配置(加强版)--netmiko + paramiko

该博客介绍了一个使用netmiko和paramiko库实现的设备配置批量备份脚本,解决了不同厂商设备配置文件中文乱码问题。通过paramiko库获取原始字节输出并按需解码,适应不同编码的设备。脚本根据设备类型选择执行命令的库,并从Excel文件读取设备信息。此外,还提供了一个简单的周期执行选项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        上次使用netmiko做了一个批量配置备份的小脚本,使用了一段时间发现一个问题。就是路由交换设备备份出来的配置能正常显示,但是部分厂商防火墙的配置备份出来中文就是乱码。

        这个问题我也是困扰了很久,到处寻医问药都是让我解码编码,根本没用。后边我发现通过netmiko库执行命令获取的设备回显的格式是字符串(str),我感觉netmiko这个库在内部就已经解码编码完毕了,输出的就是utf-8的字符。所以,我们对netmiko输出的内容怎么解码编码都没用。

        既然netmiko的输出的内容无法改变,就只能采用其他方式。要是能够将执行命令后,输出的原始字节获取到就好了,这样就可以针对设备的编码方式,对输出进行处理。最后我找到了paramiko库,这个库执行命令返回的类型是字节(bytes),这样就能根据我需要的编码进行输出了。

        这次的加强版脚本,我使用了两种库(netmiko + paramiko),在执行的时候可以自行选择。如果设备支持的不是utf-8格式(如:H3C防火墙)则可以选择paramiko库执行。正常utf-8的设备可以使用netmiko库执行。但是,netmiko连接设备真的很慢,我又不会整多线程效果可想而知。(毕业设计的时候就没整明白,反正我也不是职业开发,哈哈)

完整代码如下:

# -*- encoding: utf-8 -*-
'''
@File    :   auto_Backup_ssh_client.py
@Time    :   2021/08/01 09:16:39
@Author  :   Kun Zhou 
@Version :   1.0
@Contact :   
'''

# here put the import lib
from netmiko import ConnectHandler
from pathlib import Path
import openpyxl
import time,sys,os
import paramiko

def Read_excel(file_name):
    wb = openpyxl.load_workbook(file_name)
    sheet = wb.get_sheet_by_name('Sheet1')
    row = sheet.max_row
    column = sheet.max_column
    device_list = {}
    for i in range(2,row+1):
        device_list['device{0}'.format(i-1)] = []
        for j in range(1,column+1):
            vla = sheet.cell(row = i,column = j).value
            device_list['device{0}'.format(i-1)].append(vla)
    return device_list

def Exe_command_ssh_client(device,command_file,Backup_file_name,code ):
    if code == None:
        code = "gb2312"     #我是针对华三防火墙使用,所以默认编码是GB2312
    save = open(Backup_file_name,'a',errors='ignore')
    cmd = []
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(device["host"], 22, device["username"], device["password"])    
    for i in open(command_file,'r'):
        cmd.append(i.replace('\n',''))
    cmd_str = "\n ".join(cmd)
    stdin, stdout, stderr = ssh.exec_command(cmd_str)
    print('正在执行命令:',cmd)
    result = stdout.read().decode(code).replace('\n','')
    save.write(result)
    print("命令执行完成!")
    ssh.close() 
    print("断开连接"+ "\n\n\n")
    save.close()
    return result

def Exe_command(device,command_file,Backup_file_name):
    save = open(Backup_file_name,'a',errors='ignore')
    net_connect = ConnectHandler(**device)
    net_connect.enable()  #输入启用
    for i in open(command_file,'r'):
        cmd = i.replace('\n',' ')
        print('正在执行命令:',cmd)
        result = net_connect.send_command(cmd)
        save.write(result)
    print("命令执行完成!")
    net_connect.disconnect() 
    print("断开连接"+ "\n\n\n")
    save.close()
    return result

def Connect(device,Backup_file_name,command_file,device_type,code):
    print('正在连接{0}\n'.format(device['host']))
    if device_type == "security":
        #读取配置文件,配置文件存放在当前目录下
        Exe_command_ssh_client(device,command_file,Backup_file_name,code)
    elif device_type == "network":
        Exe_command(device,command_file,Backup_file_name)
    else:
        print(device["host"] + "\t对应的设备类型不存在!")
    

def Huawei(ip,user,passwd):  
    huawei = {
        'device_type':'huawei',
        'host':ip,
        'username':user,
        'password':passwd,
    }
    return huawei
def H3c(ip,user,passwd): #如果是display 华三需要刷入额外命令,改变屏幕显示长度
    h3c = {
        'device_type':'hp_comware',
        'host':ip,
        'username':user,
        'password':passwd,
    }
    return h3c

#
def Init(ip_file,dir_path,local_time):
    device_list = Read_excel(ip_file)
    for device_name in device_list.keys():
        try:
            if device_list[device_name][1] == 'huawei':
                device = Huawei(device_list[device_name][0],device_list[device_name][3],device_list[device_name][4])
                Backup_file_name = 'config_backup\\'+ dir_path + "\\" +device_list[device_name][2]+ "-" +local_time +'.txt'
                Connect(device,Backup_file_name,command_file = "huawei_command.txt",device_type = device_list[device_name][5],code = device_list[device_name][6])
            elif device_list[device_name][1] == 'h3c': 
                device = H3c(device_list[device_name][0],device_list[device_name][3],device_list[device_name][4])
                Backup_file_name = 'config_backup\\'+ dir_path + "\\" +device_list[device_name][2]+ "-" + local_time + '.txt'
                Connect(device,Backup_file_name,command_file = "h3c_command.txt",device_type = device_list[device_name][5],code = device_list[device_name][6])
            else:
                print('未定义设备!')
                pass
        except Exception as e:
            print('连接超时:',e)
            pass 
        time.sleep(1)

def menu():
    print("注意仅有 security 的设备类型支持选择输出编码,不填写则默认gb2312;network 类型设备不能指定编码输出!")
    print("-"*3+"选择执行周期:"+"-"*3 + "\n" +"1、一次\n" + "2、一天\n" + "3、三天\n" + "4、测试用(1小时)\n" + "5、退出\n")
    num1 = input("请输入数字:")
    if num1 == "1":
        return 99999
    elif num1 == "2":
        return 86400
    elif num1 == "3":
        return 259200
    elif num1 == "4":
        return 1800
    elif num1 == "5":
        sys.exit(0)
    else:
        print("输入有误")
        menu()

if __name__ == '__main__':
    Flag = 0
    sleep_time = menu()
    if sleep_time == 99999:
        Flag = 1
    while True:
        local_time = time.strftime("%Y-%m-%d-%H_%M_%S", time.localtime()) 
        dir_path = time.strftime("%Y-%m-%d", time.localtime()) 
        my_dir = Path("config_backup/"+dir_path+"/")
        if my_dir.exists() == False:
            os.makedirs("config_backup/"+dir_path)
        Init('ip_add.xlsx',dir_path,local_time)
        if Flag == 1:
            break
        else:
            pass
        time.sleep(sleep_time)

在该程序的目录下还需要以下几个文件或者文件夹:(exe文件忽略,是封装后的程序)

  1.  config_backup 文件夹:用于存放获取配置文件,文件夹内会根据当前日期按天生成下级目录。
  2. h3c_command.TXT和huawei_command.TXT文本文件:用于存放华三和华为的执行命令。目前我只定义了两家厂商的设备。
  3. ip_add.xlsx表格:存放设备的登陆信息,以及设备编码信息。

ip_add.xlsx格式:

  •  通过device_type可以选择执行命令的库:选择network则是使用netmiko执行;选择security是使用paramiko库执行,选择paramiko库时需要选择编码方式(code),不填写则默认GB2312
  • device_company用于区分执行命令文件。
  • device_name:为输出的配置文件名,文件名后会添加当前时间。

以上就是我的加强版设备备份程序,还请各位大佬指教。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值