标准库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)