华为交换机自动备份脚本

本人扎根数通行业多年,作为数通老油条,日常运维当中很有必要定时去备份网络设备配置命令,Python自动备份脚本结合了网络通信、文件操作、日志管理和配置管理等多个领域的知识。通过编写和使用这样的脚本,网络管理员能够自动化网络设备的维护工作,提高工作效率,同时减少人为错误。对于熟悉Python编程和网络设备操作的人员来说,这是一个非常实用的工具。

以下脚本总体来说就是:SSH登录交换机,执行dis cu 命令来查看交换机配置命令,过程中会模拟空格键使得能够获取完整的配置命令输出,将输出内容保存在本地指定路径。此方法100%有用。

脚本如下:

import paramiko
import pandas as pd
import os
import time
import datetime


# 读取交换机信息
switches_df = pd.read_excel('switches.xlsx', engine='openpyxl')

# 可自定义用于判断交换机输出结束的字符序列,默认为('\n', '\r\n'),可按需修改
END_OUTPUT_MARKER = ('\n', '\r\n')


def backup_switch_config(ip, username, password, command):
    """
    通过SSH连接到交换机,执行指定命令获取配置信息并返回
    """
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    max_read_times = 100  # 设置最大读取次数
    read_count = 0  # 记录当前读取次数
    max_retries = 3  # 设置最大重试次数
    retry_count = 0  # 记录当前重试次数

    while retry_count < max_retries:
        try:
            print(f"正在尝试连接交换机 {ip}...")
            client.connect(ip, username=username, password=password)
            print(f"已成功连接到交换机 {ip},准备发送命令...")

            # 获取一个交互式终端
            shell = client.invoke_shell()

            # 确保command是有效字符串类型且格式正确,进行更严谨处理
            if pd.isnull(command) or str(command).strip() == "":
                print(f"交换机 {ip} 的命令列值为空或格式不正确,将使用默认命令 'display current-configuration'")
                command = 'display current-configuration'
            else:
                command = str(command).strip()  # 去除两端可能的空白字符

            # 发送命令
            shell.send(command + '\n')
            print(f"已向交换机 {ip} 发送命令: {command}")
            time.sleep(1)  # 延时等待交换机响应,确保传入的是合法数字类型,这里默认等待1秒

            # 模拟长按空格键4秒,这里通过每秒发送10次空格来模拟(频率可按需调整)
            space_press_duration = 10  # 模拟长按的时长(秒)
            space_send_frequency = 10  # 每秒发送空格的次数
            for _ in range(space_press_duration * space_send_frequency):
                shell.send(' ')
                time.sleep(1 / space_send_frequency)

            output = ""
            last_output_chunk = ""  # 记录上一次读取到的输出块,用于更准确判断是否结束读取
            while True:
                print("正在尝试读取交换机输出...")
                # 读取输出
                if shell.recv_ready():
                    data = shell.recv(655350).decode()
                    output += data
                    print(f"已读取到部分输出,长度为: {len(data)} 字节,内容为: {data}")
                    read_count += 1  # 每次读取到数据,读取次数加1
                    last_output_chunk = data  # 更新上一次输出块

                    # 判断是否出现分页提示,若是则发送回车键获取下一页内容
                    if '---- More ----' in data:
                        shell.send('\n')
                        time.sleep(1)
                else:
                    print("交换机暂无输出,等待...")

                # 检查是否可以结束输出读取,综合考虑最大读取次数、换行符及输出内容变化情况
                if (read_count >= max_read_times or
                        any(marker in last_output_chunk and last_output_chunk == output[-len(last_output_chunk):] for marker in END_OUTPUT_MARKER)):
                    print("满足结束读取输出条件,结束读取。")
                    break

                if not any(marker in output[-10:] for marker in END_OUTPUT_MARKER):
                    shell.send(' \r\n')
                    time.sleep(1)  # 再次确保等待时间参数合法,默认等待1秒

            # 简单校验获取到的配置信息是否完整(这里只是示例,需完善校验逻辑)
            if is_config_complete(output):
                return output
            else:
                print("检测到获取的配置信息可能不完整,准备重试...")
                retry_count += 1
                continue
        except paramiko.AuthenticationException as e:
            print(f"连接交换机 {ip} 时认证失败: {e},请检查用户名和密码是否正确。")
            return ""
        except paramiko.SSHException as e:
            print(f"连接交换机 {ip} 出现SSH异常: {e},可能是SSH配置或网络问题,请检查相关设置。")
            return ""
        except Exception as e:
            print(f"连接交换机 {ip} 出现其他未知异常: {e},请查看详细错误信息排查问题。")
            return ""
        finally:
            client.close()
            print(f"已关闭与交换机 {ip} 的连接")

    print(f"经过 {max_retries} 次重试后,仍未能获取完整的交换机配置信息,请检查相关问题。")
    return ""


def save_backup(device_name, config):
    """
    使用时间戳生成文件名,将交换机配置保存到指定的绝对路径下的文件中
    """
    backup_dir = "C:\\SwitchConfigs"  # 设置保存备份文件的绝对路径,可按需修改
    if not os.path.exists(backup_dir):
        os.makedirs(backup_dir)
    timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
    filename = os.path.join(backup_dir, f"{device_name}_backup_{timestamp}.txt")
    print(f"准备保存备份文件,文件路径为: {filename}")
    try:
        with open(filename, 'w', encoding='utf-8') as file:
            file.write(config)
        print(f"Switch configuration backup saved as {filename}")
    except IOError as e:
        print(f"Error saving backup file {filename}: {e}")


def delete_old_backups(days=7):
    """
    删除指定绝对路径下本地指定天数之前的交换机配置备份文件
    """
    current_time = time.time()
    backup_dir = "C:\\SwitchConfigs"  # 对应保存备份文件的绝对路径

    if not os.path.exists(backup_dir):
        os.makedirs(backup_dir)

    # 删除7天前的文件
    for file in os.listdir(backup_dir):
        file_path = os.path.join(backup_dir, file)
        file_time = os.path.getmtime(file_path)
        if (current_time - file_time) // (24 * 3600) >= days:
            try:
                os.remove(file_path)
                print(f"Deleted old backup file: {file_path}")
            except OSError as e:
                print(f"Error deleting file {file_path}: {e}")


def is_config_complete(config):
    """
    简单判断配置信息是否完整的函数,这里只是示例,需根据实际情况完善更合理的校验逻辑
    比如可以计算配置内容的校验和,与完整配置的校验和对比等方式
    """
    return len(config) > 0  # 暂时简单判断长度大于0就算完整,实际需改进


def main():
    print(switches_df)
    for index, row in switches_df.iterrows():
        switch_name = str(row['Switch Name'])
        ip_address = str(row['IP Address'])
        username = str(row['Username'])
        password = str(row['Password'])
        command = str(row['Command']) if 'Command' in row else 'display current-configuration'

        print(f"Backing up configuration of {switch_name} ({ip_address})...")
        config = backup_switch_config(ip_address, username, password, command)
        if config:
            save_backup(switch_name, config)

    delete_old_backups()


if __name__ == '__main__':
    main()

switches.xlsx如下:

注意:本地保存目录需要先创建!!!!

表格信息参照实际网络设备信息更改!!!!

执行结果:

### 华为交换机配置自动备份 Shell 脚本实现方法 为了通过 Shell 脚本来实现华为交换机配置的自动备份,可以采用 Expect 工具来处理交互式的 SSH 登录过程并执行相应的命令。Expect 是一种用于自动化交互式应用程序的强大工具,在这里主要用于简化与远程设备之间的通信。 下面是一个简单的例子展示如何编写这样的脚本: ```bash #!/usr/bin/expect -f set timeout 30 set address "192.168.1.1" set username "admin" set password "yourpassword" spawn ssh -c des -q -o StrictHostKeyChecking=no $username@$address // 启动一个SSH会话[^2] expect { "*yes/no*" { send "yes\r"; exp_continue } "*assword:" { send "$password\r" } } expect ">" send "screen-length 0 temporary\r" // 防止分页影响输出结果 expect ">" send "display current-configuration\r" expect-eof log_file -a ./huawei_backup_$(date +%Y%m%d_%H%M%S).txt // 将当前时间戳加入到文件名中以便区分不同次备份的结果 ``` 此段代码首先设置了超时时间和目标地址等参数,接着利用 `spawn` 命令发起一次新的 SSH 连接请求给指定 IP 的华为交换机;之后根据提示信息输入密码完成登录验证流程;成功进入命令行界面后调整显示设置防止因屏幕长度限制而造成的数据丢失问题;最后发送指令获取现有配置并将这些数据重定向存储至本地服务器上的特定位置作为备份副本。 需要注意的是,实际部署前应当确保已安装好必要的软件包(如 expect),并且按照实际情况修改其中涉及的具体变量值比如 IP 地址、用户名以及口令等内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值