标准库telnetlib

Python3.13版本之前telnetlib为内置标准库,无需单独安装。telnetlib库用于telnet的方式与服务器交互。

Telnet登录交换机巡检实现方式

以下以多线程方式批量提取多台设备的端口流量并写入csv文件为例。

设备登录及退出函数

import telnetlib
def doTelnet(host_ip, password, username, port=23):
    tn = telnetlib.Telnet()
    try:
        tn.open(host_ip, port, timeout=5)
        print('%s connected ssuccess !' % host_ip)
        tn.read_until(b'Username:', timeout=5)
        tn.write(username.encode('ascii') + b'\n')
        tn.read_until(b'Password:', timeout=5)
        tn.write(password.encode('ascii') + b'\n')
        time.sleep(1)
        result = tn.read_until(b'#', timeout=5)
        if b'#' not in result:
            print('%s登录失败' % host_ip)
        else:
            print('%s登录成功' % host_ip)
    except:
        print('%s网络连接失败' % host_ip)
    return tn

def telnetClose(tn):
    tn.close()

指令下发函数

import re
import time
def sendCmd(tn, cmd_str):
    # 发送指令,或读取结果返回时间
    # cmd = "show ip ospf neighbor detail"
    cmd_str = bytes(cmd_str, encoding='utf-8')
    tn.write(cmd_str + b'\n')
    time.sleep(1)
    result_list = []
    while (True):
        command_result = tn.read_very_eager().decode('ascii')
        # print(command_result)
        result_list.append(command_result)
        if re.findall(r"--More--", command_result.strip()):
            # More格式处理
            tn.write(b" ")
        elif re.findall(r"#", command_result.strip()):
            break
        else:
            time.sleep(0.05)
            continue
    result_str = "\n".join(result_list)
    # run_time = re.findall(r"\d+:\d+:\d+\s+\w+\s+\w+\s+\w+\s+\d+\s+2024", result_str)[0]
    return result_str

端口流量信息提取

import pandas as pd
def get_traffic(tn, result_str):
    list_str = result_str.split('\n')
    list_temp_vec = []
    for j in list_str:
        regex = re.compile(r'\w+gei-\d+/\d+/\d+/\d+\s+.+\s+.+\d+.+\s+.+\s+.+\s+.+', re.S)
        if len(re.findall(r"Interface", j)) > 0:
            columns_name = re.split(r'\s+', j)
            columns_name = columns_name[0:7]
        if len(regex.findall(j)) > 0:
            find_str = regex.findall(j)[0]
            list_find_str = re.split(r'\s+', find_str)
            list_temp_vec.append(list_find_str)
    df_result = pd.DataFrame(list_temp_vec)
    df_result = df_result.iloc[:, :7]
    df_result.columns = columns_name
    print(f'df_result:\n{df_result.head(5)}')
    df_result = df_result[df_result['Admin'] == 'up']  # 仅提取物理端口状态为up的数据
    df_output = pd.DataFrame()
    for check_port in df_result['Interface']:
        dict_ouput = {}
        dict_ouput["port_name"] = check_port
        dict_ouput["time"] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        command = " show interface " + check_port
        result = sendCmd(tn, command)
        regex_in = re.compile(r'In_Bytes\s+(\d+)\s+')
        traffic_in = int(re.search(regex_in, str(result)).group(1))
        dict_ouput["rx_bytes"] = traffic_in
        regex_out = re.compile(r'E_Bytes\s+(\d+)\s+')
        traffic_out = int(re.search(regex_out, str(result)).group(1))
        dict_ouput["tx_bytes"] = traffic_out
        df_output = pd.concat([df_output, pd.DataFrame.from_dict([dict_ouput])], axis=0)
        df_output['time'] = pd.to_datetime(df_output['time'])
        df_output['time'] = df_output['time'].apply(lambda x: x.strftime('%Y-%m-%d %H:%M:%S'))
    return df_output

全部程序代码如下:

#!/usr/bin/python3.9
# -*- coding: UTF-8 -*-
# @Author: Ming
import os.path
import telnetlib
import re
import time
from datetime import datetime
import pandas as pd
import multiprocessing
import threading
import schedule

def doTelnet(host_ip, password, username, port=23):
    tn = telnetlib.Telnet()
    try:
        tn.open(host_ip, port, timeout=5)
        print('%s connected ssuccess !' % host_ip)
        tn.read_until(b'Username:', timeout=5)
        tn.write(username.encode('ascii') + b'\n')
        tn.read_until(b'Password:', timeout=5)
        tn.write(password.encode('ascii') + b'\n')
        time.sleep(1)
        result = tn.read_until(b'#', timeout=5)
        if b'#' not in result:
            print('%s登录失败' % host_ip)
        else:
            print('%s登录成功' % host_ip)
    except:
        print('%s网络连接失败' % host_ip)
    return tn

def sendCmd(tn, cmd_str):
    # 发送指令,或读取结果返回时间
    # cmd = "show ip ospf neighbor detail"
    cmd_str = bytes(cmd_str, encoding='utf-8')
    tn.write(cmd_str + b'\n')
    time.sleep(1)
    result_list = []
    while (True):
        command_result = tn.read_very_eager().decode('ascii')
        # print(command_result)
        result_list.append(command_result)
        if re.findall(r"--More--", command_result.strip()):
            # More格式处理
            tn.write(b" ")
        elif re.findall(r"#", command_result.strip()):
            break
        else:
            time.sleep(0.05)
            continue
    result_str = "\n".join(result_list)
    # run_time = re.findall(r"\d+:\d+:\d+\s+\w+\s+\w+\s+\w+\s+\d+\s+2024", result_str)[0]
    return result_str

def get_traffic(tn, result_str):
    list_str = result_str.split('\n')
    list_temp_vec = []
    for j in list_str:
        regex = re.compile(r'\w+gei-\d+/\d+/\d+/\d+\s+.+\s+.+\d+.+\s+.+\s+.+\s+.+', re.S)
        if len(re.findall(r"Interface", j)) > 0:
            columns_name = re.split(r'\s+', j)
            columns_name = columns_name[0:7]
        if len(regex.findall(j)) > 0:
            find_str = regex.findall(j)[0]
            list_find_str = re.split(r'\s+', find_str)
            list_temp_vec.append(list_find_str)
    df_result = pd.DataFrame(list_temp_vec)
    df_result = df_result.iloc[:, :7]
    df_result.columns = columns_name
    # print(f'df_result:\n{df_result.head(5)}')
    df_result = df_result[df_result['Phy'] == 'up']  # 仅提取物理端口状态为up的数据
    df_output = pd.DataFrame()
    for check_port in df_result['Interface']:
        dict_ouput = {}
        dict_ouput["port_name"] = check_port
        dict_ouput["time"] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        command = " show interface " + check_port
        result = sendCmd(tn, command)
        regex_in = re.compile(r'In_Bytes\s+(\d+)\s+')
        traffic_in = int(re.search(regex_in, str(result)).group(1))
        dict_ouput["rx_bytes"] = traffic_in
        regex_out = re.compile(r'E_Bytes\s+(\d+)\s+')
        traffic_out = int(re.search(regex_out, str(result)).group(1))
        dict_ouput["tx_bytes"] = traffic_out
        df_output = pd.concat([df_output, pd.DataFrame.from_dict([dict_ouput])], axis=0)
        df_output['time'] = pd.to_datetime(df_output['time'])
        df_output['time'] = df_output['time'].apply(lambda x: x.strftime('%Y-%m-%d %H:%M:%S'))
    return df_output

def fileWrite(df_data):
    if not df_data.empty:
        file = os.path.join(os.path.curdir, 'traffic.csv')
        if os.path.exists(file):
            # 已存在文件则追加模式不写入列名
            df_data.to_csv(file, index=False, mode='a', header=False)
        else:
            # 新建文件,并添加列名称
            df_data.to_csv(file, index=False, mode='a', header=True)
    else:
        print('无up状态的端口')

def telnetClose(tn):
    tn.close()

def task(host_ip):
    username = 'admin'
    password = 'admin$12345679'
    tn = doTelnet(host_ip, username, password)
    result_log = sendCmd(tn, "show interface brief")
    df_output = get_traffic(tn, result_log)
    df_output['dev_ip'] = host_ip
    fileWrite(df_output)
    tn.close()

def monitor():
    host_ip_list = ['192.168.0.1', '192.168.0.2']
    print("Begin......%s" % time.ctime())
    st = time.time()
    threads = []
    for i in range(len(host_ip_list)):
        t = threading.Thread(target=task, args=(host_ip_list[i],))
        threads.append(t)
        t.start()
    for thread in threads:
        thread.join()
    print('time cost:', time.time() - st)

if __name__ == '__main__':
    schedule.every(30).seconds.do(monitor) # 每30秒巡检一次
    while True:
        schedule.run_pending()
        time.sleep(1)

程序运行结果

写入csv文件

python使用telnet登录中兴交换机完成自动巡检_服务器交互

程序运行日志

python使用telnet登录中兴交换机完成自动巡检_网络连接_02