Netmiko是一个用于连接网络设备的Python库,该库提供了标准化的接口,使得连接诸如路由器、交换机、防火墙等各种类型的网络设备成为可能。这个库可以与Telnet、SSH等协议进行通信,并支持超过30种不同的网络厂商和设备型号。用于路由、交换、配置、监控和管理网络设备的Python脚本可以使用Netmiko实现,可用于自动化配置、端口映射、路由配置、设备查询和监控等任务。Netmiko库的主要功能包括与设备的连接、发送命令和获取输出、执行配置、收集设备信息等。Netmiko不仅大大简化了配置和管理网络设备的操作,而且提高了网络管理的效率和可靠性。
Netmiko库的优势:
- 支持多种协议:Netmiko库支持SSH、Telnet和Serial(串口)等多种协议,可以轻松访问各种品牌的网络设备,如博科、思科、华为等,免去了使用不同命令和语法的繁琐手动配置过程。
- 高度的可定制性:Netmiko支持高度可定制的配置文件,以与不同的网络设备相适应。用户可以自定义设备类型、协议、设备信息,以及处理特殊情况的脚本,提高通用性和灵活性。
- 简单易学:Netmiko使用Python编程语言,语法简单易懂,使用方便,可单独使用或与其他Python库集成使用。与传统的CLI相比,Netmiko使用命令行或脚本都可以轻松管理设备。
- 活跃的社区支持:Netmiko有一个活跃的用户社区和开发者社区,可以在GitHub上找到各种示例和脚本。这些示例和脚本可以帮助开发人员更快地上手和定制。
ref: https://pypi.org/project/netmiko/
以下脚本使用Netmiko模块以及zipfile模块,并结合具体方案,实现了备份和压缩Cisco设备配置文件,并上传到TFTP服务器的功能。脚本定义了每个设备的参数列表,并连接每个设备,保存运行配置到NVRAM和TFTP服务器。在备份过程中,脚本会输出更好的日志信息,以便于故障诊断。脚本还会压缩前一天的所有备份文件,并删除90天以前的备份文件。本脚本使用Python编写,可根据需要进行修改以适应不同的环境。
import os, zipfile, re, logging
from netmiko import ConnectHandler
from datetime import datetime, timedelta, date
# 配置日志文件
logging.basicConfig(filename='running.log', level=logging.INFO,format='%(asctime)s:%(levelname)s:%(message)s', filemode='w')
# 定义所有设备的参数列表
devices = [
{
'device_type': 'cisco_ios',
'ip': '192.168.0.26',
'username': 'cisco',
'password': '*******',
'secret': '******'
},
{
'device_type': 'cisco_ios',
'ip': '192.168.0.26',
'username': 'cisco',
'password': '*******',
'secret': '******'
}
]
# 连接和备份每个设备
for device in devices:
# 连接到设备
net_connect = ConnectHandler(**device)
# 如果有secret,则激活特权模式
if device['secret'] == 'cisco':
net_connect.enable()
# 保存设备配置至 NVRAM
logging.info(f"Start save running-config...")
backup_output = net_connect.send_command_expect('write memory', expect_string=']')
# 打印保存配置结果
if '[OK]' in backup_output:
print(f'{device["ip"]}: Configuration backup saved successfully.')
logging.info(f'{device["ip"]}: Configuration backup saved successfully.')
else:
print(f'{device["ip"]}: Failed to save configuration backup.')
logging.info(f'{device["ip"]}: Failed to save configuration backup.')
logging.info(f"End save running-config...")
logging.info(f"Start save running-config to TFTP...")
# 备份设备配置到 TFTP 服务器
tftp_address = '192.168.1.9' # TFTP 服务器的 IP 地址
filename = datetime.now().strftime("%Y%m%d%H%M%S") + '-' + device["ip"] + "-config" # 文件名
tftp_output = net_connect.send_command_timing(f'copy running-config tftp://{tftp_address}/{filename}', delay_factor=1)
while '?' in tftp_output:
net_connect.clear_buffer()
tftp_output = net_connect.send_command_timing('\n', delay_factor=20)
tftp_output += net_connect.send_command_timing('\n', delay_factor=1)
# 打印输出结果
if 'bytes copied in' in tftp_output:
for line in tftp_output.split('\n'):
if 'bytes copied in' in line:
result = line
break
if 'bytes/sec' not in result:
# 使用正则表达式从字符串中匹配数字
bytes_copied = int(re.search(r'\b(\d+)\b\s+bytes', result).group(1))
seconds = float(re.search(r'in\s+([\d.]+)\s+secs', result).group(1))
rounded_rate = round(bytes_copied / seconds)
result = f"{result} ({rounded_rate} bytes/sec)"
print(f'{device["ip"]}: Configuration successfully copied to TFTP server. {result}')
logging.info(f'{device["ip"]}: Configuration successfully copied to TFTP server. {result}')
else:
print(f'{device["ip"]}: Failed to copy configuration to TFTP server.')
logging.info(f'{device["ip"]}: Failed to copy configuration to TFTP server.')
logging.info(f"End save running-config to TFTP...")
# 断开网络连接
net_connect.disconnect()
##压缩前一日备份文件
# 备份文件夹路径
dirpath = '/tftp_folder/'
# 昨天日期
yesterday = (date.today() - timedelta(days=1)).strftime("%Y%m%d")
# 90天前日期
b90day = (date.today() - timedelta(days=90)).strftime("%Y%m%d")
# 压缩文件路径
zip_file_path = os.path.join(dirpath, f"{yesterday}.zip")
# 判断zip文件是否存在,存在则追加数据,否则创建新的zip文件
mode = 'a' if os.path.exists(zip_file_path) else 'w'
# 使用with语句打开Zip文件,自动关闭文件对象
with zipfile.ZipFile(zip_file_path, mode) as Zip:
# 获取备份文件列表
backup_files = os.listdir(dirpath)
for name in backup_files:
if name.startswith(yesterday) and not name.endswith('.zip'):
# 如果是昨天的备份文件,且不是zip文件,则添加到压缩文件中
Zip.write(os.path.join(dirpath, name), name, zipfile.ZIP_DEFLATED)
os.remove(os.path.join(dirpath, name))
elif name.endswith('.zip') and int(name[:8]) < int(b90day):
# 如果是zip文件且创建时间早于90天前,则删除文件
os.remove(os.path.join(dirpath, name))
当然以上只是一个实现需求的办法,还有很多其他的方法可以实现相同的功能。在实际的开发过程中,我们需要根据具体的需求和场景选择最合适的实现方式。不同的需求和场景需要选择最合适的实现方式,而Python作为一种简单易学、灵活性高、库丰富、跨平台性好、社区活跃的编程语言,逐渐成为了网络管理员等开发者的首选语言之一。
文末冷笑话
为什么网络管理员喜欢Python?因为他们从来都不想再通过命令行输入两个相同的命令!