Python通过SSH登录网络交换机等设备查询运行配置并保存到本地

华为交换机先设置回显不分页,这样才能显示完整,设置参考:

user-interface vty 0 4
screen-length 0

#_*_ coding:utf8 _*_
import sys, time, os
from concurrent.futures import ThreadPoolExecutor
from queue import Queue
import paramiko         # SSH 操作模块

from DEF_COLOR import *   ## 终端显示颜色

## 函数 登录SSH设备成功不关闭会话,返回ssh连接对象和交互子shell对象,后续可以在登录状态继续操作
def SSH_LOGIN(SSH_HOST, SSH_PORT, SSH_USER, SSH_PASS):
    SSH = paramiko.SSHClient()
    SSH.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        SSH.connect(SSH_HOST, SSH_PORT, SSH_USER, SSH_PASS)     # 尝试登录SSH设备
    except Exception as e:                                     # 登录失败
        return(1, f"函数 SSH_LOGIN() 登录SSH设备失败 {e}")      # 返回错误代码1和失败原因
    else:                                                       # 登录成功
        SHELL = SSH.invoke_shell()                              # 使用伪终端(子shell)(交互操作界面需要用到)
        return(0, SSH, SHELL)                                   # 返回成功代码0,ssh连接对象,交互子shell对象

## 函数 执行交互命令返回命令回显字节码
def SHELL_CMD(SHELL, CMD, TIME=2, BUFF=102400):      # 在交互子SHELL里执行操作命令并预设默认参数
    SHELL.sendall(str(CMD) + '\n')                   # 把命令转成字符串,防止类型不同不能相加
    time.sleep(TIME)                                 # 命令执行后等待足够的时间(默认2秒)以接收回显内容
    DATA_BYTES = SHELL.recv(BUFF)                    # 保存接收到的回显内容(字节码类型)(设置接收最大值为10240字节)
    return(DATA_BYTES)


# 显示用时及任务进度(每隔一段时间读取队列信息)
def 显示任务进度(q, 计时开始时间, 显示时间间隔, 任务数量):
    while 1:
        time.sleep(显示时间间隔)
        if q.empty():
            continue
        else:
            LEN_NOW = q.qsize()
            print(f"进度 {LEN_NOW/任务数量*100:.0f}% ({LEN_NOW}/{任务数量}) 已用时 {int(time.time()-计时开始时间)} 秒")
            if q.qsize() == 任务数量:
                print("完成")
                break   # 终止线程

def 线程_任务(q, TASK):
    try:
        SSH_HOST, SSH_PORT, SSH_USER, SSH_PASS, L_CMD, L_WAIT = TASK
        R = SSH_LOGIN(SSH_HOST, SSH_PORT, SSH_USER, SSH_PASS) # 尝试登录SSH设备
        if R[0] == 0:                                         # 登录成功
            SSH = R[1]                                        # 获取SSH连接对象
            SHELL = R[2]                                      # 获取可交互操作的子SHELL对象
            
            DATA_BYTES = b''
            ## 依次执行命令
            for n in range(0, len(L_CMD)):
                CMD = L_CMD[n]
                TIME = L_WAIT[n]
                #print("CMD", CMD)
                #print("TIME", TIME)
                DATA_BYTES += SHELL_CMD(SHELL, CMD, TIME)
                #print("DATA_BYTES", DATA_BYTES)
            SSH.close()
            
            q.put((0, f"{SSH_HOST}:{SSH_PORT} 操作完成", DATA_BYTES, SSH_HOST, SSH_PORT))
        else:
            ERROR = f"{SSH_HOST}:{SSH_PORT} 登录失败 {R}"
            q.put((1, ERROR, b'', SSH_HOST, SSH_PORT))                  # 结果保存到队列
            
    except Exception as e:
        ERROR = f"{SSH_HOST}:{SSH_PORT} 任务失败 {e}"
        q.put((1, ERROR, b'', SSH_HOST, SSH_PORT))

def 多线程_执行任务(L_TASK, 并发数量):
    
    TIMEOUT = 10                        # 每个连接只尝试多少秒
    q = Queue()                         # 创建一个队列
    t1 = ThreadPoolExecutor(并发数量)   # 同时运行数量,不填则默认为cpu的个数*5
    for TASK in L_TASK:
        obj=t1.submit(线程_任务, q, TASK)
    
    t2 = ThreadPoolExecutor(1)      # 新开一个线程,用于显示进度
    计时开始时间 = time.time()
    显示时间间隔 = 2                # 秒
    任务数量 = len(L_TASK)          # 任务数量
    obj=t2.submit(显示任务进度, q, 计时开始时间, 显示时间间隔, 任务数量)
    t1.shutdown()
    t2.shutdown()
    
    回显文本_合并全部设备 = ''
    N = 0
    while 1:
        N += 1
        if q.empty():
            break
        ST,INFO,DATA_BYTES,SSH_HOST,SSH_PORT = q.get()
        回显文本_单个设备 = 删除无用信息(DATA_BYTES)
        ## 各设备分别保存
        with open(f'{SSH_HOST}_{SSH_PORT}.txt', 'w', encoding='utf-8') as f:
            f.write(回显文本_单个设备)
        
        ## 全部设备合并一起显示和保存
        回显文本_合并全部设备 += 回显文本_单个设备
        #打印_紫(DATA_BYTES.decode('utf-8'))
        if ST == 0:
            打印_绿(f"{(ST,INFO)}")
            if N%2 == 0:
                打印_蓝(f"{回显文本_单个设备}")
            else:
                打印_青(f"{回显文本_单个设备}")
        else:
            打印_红(f"{(ST,INFO,DATA_BYTES)}")
        打印_灰('= = =')
    
    with open(f"{time.strftime('%Y-%m-%d')}.txt", 'w', encoding='utf-8') as f:
        f.write(回显文本_合并全部设备)
    

def 删除无用信息(DATA_BYTES):
    TEXT = ''
    TEXT_CONF = DATA_BYTES.decode('utf-8')
    L = [[j for j in i.split('\r')] for i in TEXT_CONF.split('\n')]
    for i in L:
        for j in i:
            if j.strip() != '':   # 忽略空配置行
                if j[0] not in ('*', '\x00'):      # 遇到分段符号'#'进行分段保存
                    TEXT += f"{j}\n"
    return(TEXT)

if __name__ == '__main__':
    
    ## 查看运行配置的命令及等待显示完成的时间
    L_CMD = ['dis cu']
    L_WAIT = [4]
    
    if L_WAIT == []:
        L_WAIT = [2 for i in range(len(L_CMD))] # 默认设置每个默认操作后停顿2秒
    
    ## 每个设备要执行的命令整理成任务列表
    L_TASK = []
    
    ## 设备SSH登录信息
    SSH_HOST = '192.168.56.111'
    SSH_PORT = 22
    SSH_USER = 'test'
    SSH_PASS = 'test@pwd@123'
    L_TASK.append((SSH_HOST, SSH_PORT, SSH_USER, SSH_PASS, L_CMD, L_WAIT))
    
    SSH_HOST = '192.168.56.222'
    SSH_PORT = 22
    SSH_USER = 'test'
    SSH_PASS = 'pwd@123'
    L_TASK.append((SSH_HOST, SSH_PORT, SSH_USER, SSH_PASS, L_CMD, L_WAIT))
    
    并发数量 = 10
    多线程_执行任务(L_TASK, 并发数量)
    

要看颜色的,下载 DEF_COLOR.py 放相同目录即可 http://t.csdnimg.cn/RFd2p

不要看的,修改打印部分代码即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值