基于netmiko模块实现支持SSH or Telnet的多线程多厂商网络设备自动化巡检脚本

自动化巡检的需求

巡检工作通常包含大量的重复性操作,而这些重复性特征意味着其背后存在明确的规则和逻辑。这种规律性为实现自动化提供了理想的前提条件。

自动化工具

我们这里采用python作为自动化的执行工具。

过程

安装 netmiko

python 复制代码
pip install netmiko

模块的使用

python 复制代码
import os
from concurrent.futures import ThreadPoolExecutor
from os import makedirs
from netmiko import ConnectHandler
import csv
import chardet

厂商识别与协议识别

python 复制代码
    if i['厂商'] == '华为' and i['协议'] == 'ssh':
        device_type = 'huawei'
        cmd_txt = '华为巡检命令.txt'
    elif i['厂商'] == '华为' and i['协议'] == 'telnet':
        device_type = 'huawei_telnet'
        cmd_txt = '华为巡检命令.txt'
    elif i['厂商'] == '华三' and i['协议'] == 'ssh':
        device_type = 'hp_comware'
        cmd_txt = 'H3C巡检命令.txt'
    elif i['厂商'] == '华三' and i['协议'] == 'telnet':
        device_type = 'hp_comware_telnet'
        cmd_txt = 'H3C巡检命令.txt'
    elif i['厂商'] == '锐捷' and i['协议'] == 'ssh':
        device_type = 'ruijie_os'
        cmd_txt = '锐捷巡检命令.txt'
    elif i['厂商'] == '锐捷' and i['协议'] == 'telnet':
        device_type = 'ruijie_os_telnet'
        cmd_txt = '锐捷巡检命令.txt'

创建设备字典

python 复制代码
device = {
        'device_type': device_type,
        'host': i['ip'],
        'username': i['username'],
        'password': i['password'],
    }

调用构造函数并传参,**表示将字典解包并逐一传参

python 复制代码
conn = ConnectHandler(**device)

巡检记录之path变量为True

python 复制代码
dir = os.path.join('./巡检命令文件/', cmd_txt)
    path = './巡检记录/'
    if os.path.exists(path): #表示如果path变量中存储的路径存在则运行
        with open(dir, mode='rb') as ffile: #这段open是为了识别字符集编码
            data_bs = ffile.read()
            result_dict = chardet.detect(data_bs)
            encoding_cmd_txt = result_dict['encoding']
        with open(dir, mode='r', encoding=encoding_cmd_txt) as cmd_read:
            for cmd in cmd_read:
                stdout = conn.send_command(cmd.strip())
                with open(f'{path}{i['ip']}的巡检记录.txt', mode='a', encoding='utf-8') as addwrite:
                    addwrite.write(stdout)

巡检记录之path变量为false

python 复制代码
    else:
        makedirs(path)  #因为path变量中存储的路径不存在,因此创建一个
        with open(dir, mode='rb') as ffile:
            data_bs = ffile.read()
            result_dict = chardet.detect(data_bs)
            encoding_cmd_txt = result_dict['encoding']
        with open(dir, mode='r', encoding=encoding_cmd_txt) as cmd_read:
            for cmd in cmd_read:
                stdout = conn.send_command(cmd.strip())
                with open(f'{path}{i['ip']}的巡检记录.txt', mode='a', encoding='utf-8') as addwrite:
                    addwrite.write(stdout)

并且以上所有代码细节都封装进一个函数里以方便代码的抽象化引用和减少代码的重复性。

python 复制代码
def xijie(i):
    if i['厂商'] == '华为' and i['协议'] == 'ssh':
        device_type = 'huawei'
        cmd_txt = '华为巡检命令.txt'
    elif i['厂商'] == '华为' and i['协议'] == 'telnet':
        device_type = 'huawei_telnet'
        cmd_txt = '华为巡检命令.txt'
    elif i['厂商'] == '华三' and i['协议'] == 'ssh':
        device_type = 'hp_comware'
        cmd_txt = 'H3C巡检命令.txt'
    elif i['厂商'] == '华三' and i['协议'] == 'telnet':
        device_type = 'hp_comware_telnet'
        cmd_txt = 'H3C巡检命令.txt'
    elif i['厂商'] == '锐捷' and i['协议'] == 'ssh':
        device_type = 'ruijie_os'
        cmd_txt = '锐捷巡检命令.txt'
    elif i['厂商'] == '锐捷' and i['协议'] == 'telnet':
        device_type = 'ruijie_os_telnet'
        cmd_txt = '锐捷巡检命令.txt'
    device = {
        'device_type': device_type,
        'host': i['ip'],
        'username': i['username'],
        'password': i['password'],
    }
    conn = ConnectHandler(**device)
    dir = os.path.join('./巡检命令文件/', cmd_txt)
    path = './巡检记录/'
    if os.path.exists(path):
        with open(dir, mode='rb') as ffile:
            data_bs = ffile.read()
            result_dict = chardet.detect(data_bs)
            encoding_cmd_txt = result_dict['encoding']
        with open(dir, mode='r', encoding=encoding_cmd_txt) as cmd_read:
            for cmd in cmd_read:
                stdout = conn.send_command(cmd.strip())
                with open(f'{path}{i['ip']}的巡检记录.txt', mode='a', encoding='utf-8') as addwrite:
                    addwrite.write(stdout)
    else:
        makedirs(path)
        with open(dir, mode='rb') as ffile:
            data_bs = ffile.read()
            result_dict = chardet.detect(data_bs)
            encoding_cmd_txt = result_dict['encoding']
        with open(dir, mode='r', encoding=encoding_cmd_txt) as cmd_read:
            for cmd in cmd_read:
                stdout = conn.send_command(cmd.strip())
                with open(f'{path}{i['ip']}的巡检记录.txt', mode='a', encoding='utf-8') as addwrite:
                    addwrite.write(stdout)

主程序入口点

python 复制代码
if __name__ == '__main__':
    with open('host.csv',mode='rb') as file:
            raw_data = file.read()
            result = chardet.detect(raw_data)
            encoding = result['encoding']
    with open('host.csv',mode='r',encoding=encoding) as file:
            reader = csv.DictReader(file)
            max_thread = 10 #定义线程池中使用多少线程
            for i in reader:
               with ThreadPoolExecutor(max_workers=max_thread) as t:
                   t.submit(xijie,i) #提交任务

可以看出,由于将代码细节给抽象化成函数,因此整个代码显得更简洁了,特别是在主程序入口的体现,无需了解代码细节,直接引用即可。

具体代码实现

python 复制代码
import os
from concurrent.futures import ThreadPoolExecutor
from os import makedirs
from netmiko import ConnectHandler
import csv
import chardet

def xijie(i):
    if i['厂商'] == '华为' and i['协议'] == 'ssh':
        device_type = 'huawei'
        cmd_txt = '华为巡检命令.txt'
    elif i['厂商'] == '华为' and i['协议'] == 'telnet':
        device_type = 'huawei_telnet'
        cmd_txt = '华为巡检命令.txt'
    elif i['厂商'] == '华三' and i['协议'] == 'ssh':
        device_type = 'hp_comware'
        cmd_txt = 'H3C巡检命令.txt'
    elif i['厂商'] == '华三' and i['协议'] == 'telnet':
        device_type = 'hp_comware_telnet'
        cmd_txt = 'H3C巡检命令.txt'
    elif i['厂商'] == '锐捷' and i['协议'] == 'ssh':
        device_type = 'ruijie_os'
        cmd_txt = '锐捷巡检命令.txt'
    elif i['厂商'] == '锐捷' and i['协议'] == 'telnet':
        device_type = 'ruijie_os_telnet'
        cmd_txt = '锐捷巡检命令.txt'
    device = {
        'device_type': device_type,
        'host': i['ip'],
        'username': i['username'],
        'password': i['password'],
    }
    conn = ConnectHandler(**device)
    dir = os.path.join('./巡检命令文件/', cmd_txt)
    path = './巡检记录/'
    if os.path.exists(path):
        with open(dir, mode='rb') as ffile:
            data_bs = ffile.read()
            result_dict = chardet.detect(data_bs)
            encoding_cmd_txt = result_dict['encoding']
        with open(dir, mode='r', encoding=encoding_cmd_txt) as cmd_read:
            for cmd in cmd_read:
                stdout = conn.send_command(cmd.strip())
                with open(f'{path}{i['ip']}的巡检记录.txt', mode='a', encoding='utf-8') as addwrite:
                    addwrite.write(stdout)
    else:
        makedirs(path)
        with open(dir, mode='rb') as ffile:
            data_bs = ffile.read()
            result_dict = chardet.detect(data_bs)
            encoding_cmd_txt = result_dict['encoding']
        with open(dir, mode='r', encoding=encoding_cmd_txt) as cmd_read:
            for cmd in cmd_read:
                stdout = conn.send_command(cmd.strip())
                with open(f'{path}{i['ip']}的巡检记录.txt', mode='a', encoding='utf-8') as addwrite:
                    addwrite.write(stdout)

if __name__ == '__main__':
    with open('host.csv',mode='rb') as file:
            raw_data = file.read()
            result = chardet.detect(raw_data)
            encoding = result['encoding']
    with open('host.csv',mode='r',encoding=encoding) as file:
            reader = csv.DictReader(file)
            max_thread = 10
            for i in reader:
               with ThreadPoolExecutor(max_workers=max_thread) as t:
                   t.submit(xijie,i)
相关推荐
金銀銅鐵6 小时前
[Python] 基于欧几里得算法,实现分数约分计算器
python·数学
Lyn_Li8 小时前
Kaggle Top 5 | 198只股票、200条数据的金融预测——BattleFin高分方案从零复现
python·kaggle·比赛复盘·金融预测
SkyWalking中文站12 小时前
认识 Horizon UI · 1/17:SkyWalking 新一代可观测性控制台
运维·前端·监控
小九九的爸爸12 小时前
前端想要入门Agent开发,要具备哪些Python基础?
python·agent·ai编程
阿耶同学13 小时前
手把手教你用 LangGraph 搭建三层嵌套 Agent 架构
python·程序员
雪梨酱QAQ15 小时前
Kubeneters HA Cluster部署
运维
江华森19 小时前
Spring Cloud 微服务全栈实战:从 Eureka 到 Docker Compose 一文贯通
运维
江华森19 小时前
Matplotlib 数据绘图基础入门
运维
江华森19 小时前
NumPy 数值计算基础入门
运维
花酒锄作田1 天前
Pydantic校验配置文件
python