网络安全-用脚本调用系统snmpwalk命令查询并邮件报警

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
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值