使用paramiko模块ssh连接实现交换机配置自动备份
将devices_list.txt和network_backup.py文件放在同一目录内
编辑内容如下
172.16.0.1 1F01 startup.cfg
172.16.0.2 2F01 vrpcfg.zip
172.16.0.3 3F01 vrpcfg.zip
172.16.0.4 4F01 startup.cfg
172.16.0.5 5F01 startup.cfg
直接运行network_backup.py,利用FTP上传配置文件,即可完成自动批量备份交换机
Python 代码:
import paramiko
import time
import os
import logging
# 配置日志,指定日志文件路径
log_file_path = 'log.txt'
# 创建文件处理器,记录所有级别的日志
file_handler = logging.FileHandler(log_file_path, mode='w')
file_handler.setLevel(logging.DEBUG)
# 创建终端处理器,仅显示INFO及以上级别的日志
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# 配置日志格式
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
# 获取根日志记录器,并添加处理器
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
logger.addHandler(file_handler)
logger.addHandler(console_handler)
# 从环境变量获取用户名和密码
username = os.getenv('SSH_USERNAME', '用户名')
password = os.getenv('SSH_PASSWORD', '密码')
# FTP 服务器信息
ftp_server = 'FTP服务器'
ftp_user = 'FTP账号'
ftp_password = 'FTP密码'
# 打开设备列表文件
with open('devices_list.txt', 'r') as f:
devices = f.readlines()
total_devices = len(devices)
success_count = 0 # 上传成功计数
failure_count = 0 # 上传失败计数
success_devices = [] # 记录上传成功的设备信息
failure_devices = [] # 记录上传失败的设备信息
for index, line in enumerate(devices):
line_s = line.strip().split()
# 检查行是否为空或是否有足够的列
if not line_s or len(line_s) < 2:
logging.warning(f"行格式不正确或为空,跳过: {line.strip()}")
continue
device_ip = line_s[0]
device_name = line_s[1]
# 判断备份文件类型
if len(line_s) > 2:
backup_file = line_s[2] # 第三列为备份文件名
else:
backup_file = 'startup.cfg' # 默认文件名
try:
# 创建 SSH 客户端并设置策略
with paramiko.SSHClient() as ssh_client:
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname=device_ip, username=username, password=password)
# 仅在终端显示 SSH 连接成功
print(f'成功连接上 {device_ip}')
logging.info(f'成功连接上 {device_ip}')
# 通过 SSH 会话发送命令
command = ssh_client.invoke_shell()
# 发送命令并接收输出的函数
def send_and_receive(command_str, expected_output=None, sleep_time=2):
command.send(command_str + '\n')
time.sleep(sleep_time) # 增加等待时间
output = ''
while True:
if command.recv_ready():
output += command.recv(1024).decode('utf-8')
else:
break
logging.debug(f'发送命令: {command_str}, 接收响应: {output}')
if expected_output is not None:
if expected_output in output:
logging.info(f'收到预期输出: {expected_output}')
else:
logging.warning(f'未收到预期输出: {expected_output}')
return output
# 执行 FTP 命令
output = send_and_receive(f'ftp {ftp_server}', sleep_time=8)
# 输出FTP命令的初始响应
logging.debug(f'FTP命令初始响应: {output}')
# 确认设备是否要求用户名
if "User" in output or "Name" in output or "Login:" in output:
output = send_and_receive(ftp_user, sleep_time=2)
else:
print(f'FTP连接失败: {device_ip}')
logging.warning(f'未收到FTP用户名提示,可能未能正确连接到FTP服务器: {device_ip}')
failure_count += 1
failure_devices.append(f"{device_ip} ({device_name})") # 记录失败设备
continue
# 发送密码并确认登录成功
if "Password" in output or "Password:" in output:
output = send_and_receive(ftp_password, sleep_time=2)
if "230" in output or "Login successful" in output:
# 仅在终端显示 FTP 连接成功
print(f'FTP 登录成功: {device_ip}')
logging.info(f'FTP 登录成功: {device_ip}')
else:
print(f'FTP 登录失败: {device_ip}')
logging.warning(f'FTP 登录失败: {device_ip}')
failure_count += 1
failure_devices.append(f"{device_ip} ({device_name})") # 记录失败设备
continue
else:
print(f'FTP登录失败: {device_ip}')
logging.warning(f'未收到FTP密码提示,可能未能正确登录: {device_ip}')
failure_count += 1
failure_devices.append(f"{device_ip} ({device_name})") # 记录失败设备
continue
# 上传文件并检查是否成功
output = send_and_receive(f'put {backup_file} {device_name}_{backup_file}', '226 Transfer complete',
sleep_time=2)
logging.debug(f'FTP 上传响应: {output}') # 记录完整的 FTP 上传响应
send_and_receive('quit', sleep_time=1) # 退出 FTP
# 检查输出是否包含 "226 Transfer complete"
if "226 Transfer complete" in output:
# 仅在终端显示上传成功的信息
print(f'文件上传成功: {device_ip}')
logging.info(f'文件上传成功: {device_ip}')
success_count += 1
success_devices.append(f"{device_ip} ({device_name})")
else:
print(f'文件上传失败: {device_ip}')
logging.warning(f'文件上传失败: {device_ip}')
failure_count += 1
failure_devices.append(f"{device_ip} ({device_name})") # 记录失败设备
except Exception as e:
print(f'连接 {device_ip} 失败')
logging.error(f'连接 {device_ip} 失败: {e}')
failure_count += 1
failure_devices.append(f"{device_ip} ({device_name})") # 记录失败设备
# 统计上传结果
print(f'总共设备数量: {success_count + failure_count}')
logging.info(f'总共设备数量: {success_count + failure_count}')
print(f'文件上传成功的设备数量: {success_count}')
logging.info(f'文件上传成功的设备数量: {success_count}')
print(f'文件上传失败的设备数量: {failure_count}')
logging.info(f'文件上传失败的设备数量: {failure_count}')
# 将统计信息和成功、失败设备信息写入 备份结果.txt 文件
with open('备份结果.txt', 'w') as report_file:
report_file.write(f'总共设备数量: {success_count + failure_count}\n')
report_file.write(f'文件上传成功的设备数量: {success_count}\n')
report_file.write(f'文件上传失败的设备数量: {failure_count}\n\n')
report_file.write('成功上传的设备列表:\n')
for device in success_devices:
report_file.write(f'{device}\n')
report_file.write('\n上传失败的设备列表:\n')
for device in failure_devices:
report_file.write(f'{device}\n')
# 等待一段时间再结束脚本
time.sleep(3)
input("按任意键退出...")
评论区