SNMP.py
Linux系统,安装snmpwalk,python3
#!/usr/bin/python3
#_*_ coding:utf8 _*_
import os,time,re,subprocess
import smtplib
from smtplib import SMTP
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header
from concurrent.futures import ThreadPoolExecutor
from queue import Queue
## snmp OID
# snmpwalk -v 2c -c snmp读密码 SNMP服务器IP .1.3.6.1.2.1.25.3.3.1.2 # CPU负载
# snmpwalk -v 2c -c snmp读密码 SNMP服务器IP HOST-RESOURCES-MIB::hrProcessorLoad # CPU负载
# snmpwalk -v 2c -c snmp读密码 SNMP服务器IP 1.3.6.1.2.1.25.2 # 内存、硬盘使用率
# snmpwalk -v 2c -c snmp读密码 SNMP服务器IP 1.3.6.1.2.1.25 # 进程使用cpu信息、进程使用内存信息,及内存、硬盘使用率
## 发邮件通知,设置邮件内容
def 纯文本邮件内容对象(邮件主题, 邮件正文, 发件人, 收件人):
#创建一个带附件的实例
message = MIMEMultipart()
message['From'] = Header(发件人, 'utf-8')
message['To'] = Header(收件人, 'utf-8')
# 邮件主题
subject = 邮件主题
message['Subject'] = Header(subject, 'utf-8')
# 邮件正文,纯文本
TEXT = MIMEText(邮件正文, 'plain', 'utf-8')
message.attach(TEXT)
return(message)
def 批量发邮件(SMTP_SERVER, 发件人, 邮箱密码, L_邮件任务):
try:
client = smtplib.SMTP()
#client = smtplib.SMTP_SSL() # 需要使用SSL,可以这样创建client
client.connect(SMTP_SERVER, 25)
#client.set_debuglevel(1) # 开启DEBUG模式
client.login(发件人, 邮箱密码)
#except smtplib.SMTPConnectError as e:
# print('邮件发送失败,连接失败:', e.smtp_code, e.smtp_error)
#except smtplib.SMTPAuthenticationError as e:
# print('邮件发送失败,认证错误:', e.smtp_code, e.smtp_error)
#except smtplib.SMTPSenderRefused as e:
# print('邮件发送失败,发件人被拒绝:', e.smtp_code, e.smtp_error)
#except smtplib.SMTPRecipientsRefused as e:
# print('邮件发送失败,收件人被拒绝:', e.smtp_code, e.smtp_error)
#except smtplib.SMTPDataError as e:
# print('邮件发送失败,数据接收拒绝:', e.smtp_code, e.smtp_error)
#except smtplib.SMTPException as e:
# print('邮件发送失败, ', e.message)
except Exception as e:
print(f"邮件发送异常 {e}")
else:
for 收件人,邮件主题,邮件正文 in L_邮件任务:
time.sleep(2)
message = 纯文本邮件内容对象(邮件主题, 邮件正文, 发件人, 收件人)
try:
client.sendmail(发件人, 收件人, message.as_string())
except Exception as e:
print(e)
else:
print(f"{time.strftime('%Y%m%d')} 发送成功: {收件人:32s} {邮件主题}")
client.quit()
print("发送完成")
## 获取CPU占用最高的前N个进程信息
def SHOW_PID_CPU_TOP_N(N, D_PID_NAME, D_PID_CPU):
R_L_PID_CPU_TOP_N = []
L_PID_CPU = [D_PID_CPU[i] for i in D_PID_CPU] # 从D_PID_CPU字典中提取CPU占用量值做成列表
L_PID_CPU.sort(reverse=True) # 从大到小排序
for i in L_PID_CPU[0:N]: # 取开头N个
for PID,PerfCPU in D_PID_CPU.items():
if i == PerfCPU:
PID_NAME = D_PID_NAME[PID]
R_TEXT = str(PID_NAME) + ' ' + str(PerfCPU)
R_L_PID_CPU_TOP_N.append(R_TEXT)
return(R_L_PID_CPU_TOP_N)
## 获取内存占用最高的前N个进程信息
def SHOW_PID_MEM_TOP_N(N, D_PID_NAME, D_PID_MEM):
R_L_PID_MEM_TOP_N = []
L_PID_MEM = [D_PID_MEM[i] for i in D_PID_MEM]
L_PID_MEM.sort(reverse=True) # 从大大小排序
for i in L_PID_MEM[0:N]: # 取开头N个
for PID,PerfMem in D_PID_MEM.items():
if i == PerfMem:
PID_NAME = D_PID_NAME[PID]
R_TEXT = str(PID_NAME) + ' ' + str(PerfMem) + ' KBytes'
R_L_PID_MEM_TOP_N.append(R_TEXT)
return(R_L_PID_MEM_TOP_N)
## 处理SNMP查询结果,查CPU及内存,生成字典,方便使用
'''
# 进程名
HOST-RESOURCES-MIB::hrSWRunName.1 = STRING: "System Idle Process"
HOST-RESOURCES-MIB::hrSWRunName.4 = STRING: "System"
# 进程占用CPU
HOST-RESOURCES-MIB::hrSWRunPerfCPU.1 = INTEGER: 88064
HOST-RESOURCES-MIB::hrSWRunPerfCPU.4 = INTEGER: 725
# 进程使用内存
HOST-RESOURCES-MIB::hrSWRunPerfMem.1 = INTEGER: 4 KBytes
HOST-RESOURCES-MIB::hrSWRunPerfMem.4 = INTEGER: 140 KBytes
'''
def PID_NAME_CPU_MEM(output):
D_PID_NAME = {} # Key:'进程号', Value:'进程名'
D_PID_CPU = {} # Key:'进程号', Value:进程占用CPU时间(数值)
D_PID_MEM = {} # Key:'进程号', Value:进程占用内存数值(KBytes)
RE_PID = "(HOST-RESOURCES-MIB::hrSWRunName(.*))|(HOST-RESOURCES-MIB::hrSWRunPerfCPU(.*))|(HOST-RESOURCES-MIB::hrSWRunPerfMem(.*))" # SNMP返回结果用的RE过滤规则
R = re.finditer(RE_PID, output)
L_PID_INFO = [i.group() for i in R]
for i in L_PID_INFO: # 'HOST-RESOURCES-MIB::hrSWRunName.1 = STRING: "System Idle Process"'
K,V = i.split(' = ') # 分割为 'HOST-RESOURCES-MIB::hrSWRunName.1' 和 'STRING: "System Idle Process"'
NAME,INDEX = K.split('.') # 分割为 'HOST-RESOURCES-MIB::hrSWRunName' 和 '1'
if NAME == 'HOST-RESOURCES-MIB::hrSWRunName':
VV = V.split(': ')[-1] # 从 STRING: "System Idle Process" 中提取 "System Idle Process"
D_PID_NAME[INDEX] = VV # {'1':"System Idle Process"}
elif NAME == 'HOST-RESOURCES-MIB::hrSWRunPerfCPU':
VV = int(V.split(': ')[-1])
D_PID_CPU[INDEX] = VV # {'1': 88064}
elif NAME == 'HOST-RESOURCES-MIB::hrSWRunPerfMem':
VV = V.split(': ')[-1]
PID_MEM = int(VV.split(' ')[0])
D_PID_MEM[INDEX] = PID_MEM # {'1':4}
return(D_PID_NAME, D_PID_CPU, D_PID_MEM)
def 单位转换(INT, UNIT):
if UNIT == 'Bytes':
X = round(INT/1024/1024/1024)
return(f"{X}GB")
else:
return(f"{INT}{UNIT}")
## 执行SNMP命令获取CPU、内存、硬盘分区使用率信息
## 返回 (StatusCode, SYS_INFO, D_SYS_INFO)
## StatusCode 含义: 0 成功,1 查CPU失败,2 查MEM/DISK失败,3 查CPU/MEM/DISK都失败
## SYS_INFO (文本)字典类型存储CPU/MEM/DISK的使用率百分比
def SNMP_CPU_MEM_DISK_USED(SYSTEM, SNMP_HOST, SNMP_PWD):
D_SYS_INFO = {'CPU':-1, 'MEM':-1, 'SWAP':-1, 'DISK':{}}
SYS_INFO = '' # 记录查询分析结果
StatusCode = 0 # 函数执行结果状态码,SNMP命令执行情况:0 正常,1 获取CPU使用率的SNMP命令失败,2 获取CPU/内存/硬盘信息的SNMP命令失败,3 两个全部失败
## 获取CPU使用率的SNMP命令
CMD = 'snmpwalk -v 2c -c ' + SNMP_PWD + ' ' + SNMP_HOST + ' HOST-RESOURCES-MIB::hrProcessorLoad'
(CPU_status,CPU_output) = subprocess.getstatusoutput(CMD) # 执行命令
#print CPU_status
#print CPU_output
## 获取内存、硬盘使用率的SNMP命令
CMD = 'snmpwalk -v 2c -c ' + SNMP_PWD + ' ' + SNMP_HOST + ' 1.3.6.1.2.1.25.2'
(MEM_DISK_status,ALL_output) = subprocess.getstatusoutput(CMD) # 执行命令
#print(CMD)
#print MEM_DISK_status
#print ALL_output