IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 「Python 网络自动化」Paramiko —— 使用 Paramiko 连接网络设备执行命令 多线程并发 -> 正文阅读

[系统运维]「Python 网络自动化」Paramiko —— 使用 Paramiko 连接网络设备执行命令 多线程并发

插播:Nornir 是一个非常好用的网络自动化的框架,最近我输出了一份 Nornir 中文手册,欢迎大家阅读指正。

背景

最近公司内网设备版本有些问题,会出现队列丢包现象,由于设备较多,写个脚本定期收集会方便一点,不过内网只有 paramiko,所以简单造了一个轮子,实现多线程并发登录设备执行命令并对结果进行解析。

用这个脚本可以在网络设备上执行任何命令,实现各种功能,而且多线程并发很 Nice!

本次用到的命令及输出示例如下:
# [H3C]dis qos queue-statistics interface outbound | in "^ Drop"
#  Dropped: 0 packets, 0 bytes

这个命令用来收集当前设备上所有接口的所有队列的转发信息累计值(bytes 和 packages)。

主要思路

代码比较简单,主要还是 paramiko 的 SSH 基本用法,这里说一下大概思路:

  1. 把所有设备信息写到一个文本文档里面,简单起见,用的是 txt,把登录信息构建成字典
  2. 写一个类,具有两个功能:初始化 SSH 连接、执行命令
  3. 对本次需求指定的命令及输出结果进行解析,并将结果存入文件
  4. 加入多线程执行,提高效率
  5. 添加 Linux 的 crontab,每小时收集一次信息 (在服务器上做的配置)

代码

代码地址:在线查看代码

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
import time
from concurrent.futures import ThreadPoolExecutor
import paramiko


def get_device_list(filename):
    """从文本文件读取设备列表,返回由字典组成的列表。
    文本内容格式为:ip,用户名,密码,别名,例如:
    1.1.1.1 admin admin sw1
    1.1.1.2 admin admin sw2
    ......
    
    Args:
        filename ([str]): 文件名称
    """
    with open(filename, 'r') as f:
        device_list = []
        for line in f.readlines():
            ip, username, password, name = line.strip().split()
            device_list.append(
                {
                    "ip": ip,
                    "username": username,
                    "password": password,
                    "name": name,
                }
            )
    return device_list

class NetworkDevice(object):
    def __init__(self, ip="", username="", password="'", name="", port=22,):
        self.conn = None
        if ip:
            self.ip = ip.strip()
        elif name:
            self.name = name.strip()
        else:
            raise ValueError("需要设备连接地址(ip 或 别名)")
        self.port = int(port)
        self.username = username
        self.password = password
        self._open_ssh()
    
    def _open_ssh(self):
        """初始化 SSH 连接,调起一个模拟终端,会话结束前可以一直执行命令。

        Raises:
            e: 抛出 paramiko 连接失败的任何异常

        """
        ssh_connect_params = {
            "hostname": self.ip,
            "port": self.port,
            "username": self.username,
            "password": self.password,
            "look_for_keys": False,
            "allow_agent": False,
            "timeout": 5,   # TCP 连接超时时间
        }
        conn = paramiko.SSHClient()
        conn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            conn.connect(**ssh_connect_params)
        except Exception as e:
            raise e
        self.conn = conn.invoke_shell(term="vt100", width=500, height=1000)
        return ""

    def exec_cmd(self, cmd, recv_time=3):
        """登录设备,执行命令

        Args:
            cmd ([type]): 命令字符串
            recv_time (int, optional): 读取回显信息的超时时间. Defaults to 3.

        Raises:
            EOFError: 没有任何信息输出,说明连接失败。

        Returns:
            output: 
        """
        cmd = cmd.strip() + "\n"
        self.conn.sendall("screen disable\n")
        self.conn.sendall(cmd)
        time.sleep(int(recv_time))
        output = self.conn.recv(1024*1024)
        if len(output) == 0:
            raise EOFError("连接可能被关闭,没有任何信息输出")
        return output.decode('utf-8', 'ignore')


dev = {
    "ip":"192.168.56.21",
    "username":"netdevops",
    "password":"Admin@h3c.com",
    "name": "sw1"
}
# sw1 = NetworkDevice(**dev)
# ret = sw1.exec_cmd("dis version")
# print(ret)

def parse_interface_drop(output):
    """把设备的输出队列丢包信息解析成累加值
    命令及输出示例如下:
    # [H3C]dis qos queue-statistics interface outbound | in "^ Drop"
    #  Dropped: 0 packets, 0 bytes
    """
    ptn = re.compile(r"\s(\S+):\s+(\d+)\s+(\S+),\s+(\d+)\s+(\S+)")
    count = 0
    for i in ptn.findall(output):
        count += int(i[1])
    return count

def run(cmd, **conn_parms):
    """登录单台设备,执行指定命令,解析丢包统计
    """
    sw = NetworkDevice(**conn_parms)
    output = sw.exec_cmd(cmd)
    drop_count = parse_interface_drop(output)
    return "%s %s %s"%(
        conn_parms.get("name"),
        conn_parms.get("ip"),
        drop_count)

# cmd = r'dis qos queue-statistics interface outbound | in "^ Drop"'
# ret = run(cmd,**dev)
# print(ret)

if __name__== "__main__":
    """获取设备列表,使用多线程登录设备获取信息并返回
    """
    with ThreadPoolExecutor(10) as pool:
        futures = []
        cmd = r'dis qos queue-statistics interface outbound | in "^ Drop"'
        dev_info = get_device_list("./iplist.txt")
        for d in dev_info:
            future = pool.submit(run, cmd, **d)
            futures.append(future)
        # for f in futures:
        #     print(f.result())
    # 根据执行时间把结果写入文件,精确到小时
    with open("./drops/%s.log"%time.strftime("%Y%m%d_%H"),'w') as f:
         for line in futures:
            f.write(line.result() + "\n")
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-08-23 17:05:14  更:2021-08-23 17:06:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 20:59:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计