华为交换机先设置回显不分页,这样才能显示完整,设置参考:
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
不要看的,修改打印部分代码即可