python中使用gevent协程实现系统监控报警


文章目录

  • python中使用gevent协程实现系统监控报警
  • 一、版本说明
  • 二、主要逻辑与功能
  • 三、整体代码
  • 四、未解决问题


一、版本说明

版本

更新日期

1.0.Alpha

2022-02-26

二、主要逻辑与功能

主要功能还是监控系统信息并报警

  1. 内存利用率大于80%。发送告警邮件
  2. CPU利用率大于80%。发送告警邮件
  3. 每晚12点定时发送系统信息,包括但不限于网卡信息、主机名与IP地址

三、整体代码

代码逻辑比较简单,很容易就能看懂

注意:请修改代码中的邮件发送参数,具体百度网易邮箱开启SMTP

代码如下:

import psutil, time, logging, gevent, smtplib, datetime, schedule, socket
from gevent import monkey
from email.mime.text import MIMEText
from logging import handlers

fomatter = logging.Formatter(' %(levelname)s %(asctime)s - %(funcName)s - %(thread)s [%(message)s]')
# 创建日志器对象
logger = logging.getLogger()
# 日志级别总开关
logger.setLevel("INFO")
# 设置日志文件
logFile = './default_monitor.log'
# 创建日志文件hander
# fileHandler = logging.FileHandler(logFile, mode='a')
# fileHandler.setLevel(logging.INFO)
# 创建控制台hander
console_hander = logging.StreamHandler()
# 创建控制台hander日志等级
console_hander.setLevel(level='INFO')
# 设置日志格式
console_hander.setFormatter(fomatter)
th = handlers.TimedRotatingFileHandler(filename=logFile, when='D', backupCount=3, encoding='utf-8')
th.setFormatter(fomatter)
th.setLevel(level='INFO')
# 添加日志hander
logger.addHandler(console_hander)
logger.addHandler(th)
# logger.addHandler(fileHandler)

# 设置邮件发送参数,需要自己修改成自己的参数
mail_host = 'smtp.163.com'
mail_user = 'cc17854388872@163.com'
mail_pass = 'VBYZZtttttRDQJAXN'
sender = 'cc17854388872@163.com'
# 接收方邮箱地址
receivers = ['1849999179@qq.com']
# 获取当前时间
current_time = datetime.datetime.now()

# 使用gevent中的monky不修改原来使用的python标准库函数的程序的情况下,将程序转换成可以使用gevent框架的异步程序。
monkey.patch_all()


def print_system_info(mem, cpu):
    while True:
        # 闲的没事干加点日志输出吧
        logger.info(f'Current Memory utilization is {mem.percent}%')
        logger.info(f'Current CPU utilization is {cpu}%')
        time.sleep(10)


# 系统信息定时发送函数
def system_sender():
    # 创建任务调用mail_sender并传递两个参数,每天晚上12点定时发送系统信息邮件
    schedule.every().day.at("20:37").do(mail_sender, title='system info', content=get_system())
    logger.info('scheduler starting ')
    while True:
        schedule.run_pending()
        time.sleep(1)


# 获取系统信息函数
def get_system():
    date = ""
    # 服务器基本信息,主机名与IP地址
    myname = socket.getfqdn(socket.gethostname())
    myaddr = socket.gethostbyname(myname)

    # 用户信息
    now_time = time.strftime('%Y-%m-%d-%H:%M:%S', time.localtime(time.time()))
    start_time = datetime.datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H: %M: %S")

    # CPU信息
    cpu_num = psutil.cpu_count(logical=False)
    cpu = (str(psutil.cpu_percent(1))) + '%'

    # 内存信息
    total = str(round(psutil.virtual_memory().total / (1024.0 * 1024.0 * 1024.0), 2)) + 'G'
    total_used = str(round(psutil.virtual_memory().used / (1024.0 * 1024.0 * 1024.0), 2)) + 'G'
    total_free = str(round(psutil.virtual_memory().free / (1024.0 * 1024.0 * 1024.0), 2)) + 'G'
    memory = str(psutil.virtual_memory().percent) + '%'

    # 网卡信息
    net = psutil.net_io_counters()
    bytes_sent = '{0:.2f} Mb'.format(net.bytes_recv / 1024 / 1024)
    bytes_rcvd = '{0:.2f} Mb'.format(net.bytes_sent / 1024 / 1024)

    date += "<br/>当前用户: " + str(psutil.users()[0][0]) + '<br/>'
    date += "<br/>当前主机:" + str(myname) + '<br/>'
    date += "<br/>IP 地址: " + myaddr + '<br/>'
    date += "<br/>系统当前时间: " + now_time + '<br/>'
    date += "<br/>系统开机时间: " + start_time + '<br/>'
    date += "<br/>CPU个数: " + str(cpu_num) + '<br/>'
    date += "<br/>CPU使用率: " + cpu + '<br/>'
    date += "<br/>内存: " + total + '<br/>'
    date += "<br/>内存已使用: " + total_used + '<br/>'
    date += "<br/>剩余内存: " + total_free + '<br/>'
    date += "<br/>内存使用率: " + memory + '<br/>'
    date += "<br/>网卡发送流量: " + bytes_sent + '<br/>'
    date += "<br/>网卡接收流量: " + bytes_rcvd + '<br/>'
    return date


def mail_sender(title, content):
    message = MIMEText(content, 'plain', 'utf-8')
    message['Subject'] = title
    message['From'] = sender
    message['To'] = receivers[0]
    try:
        smtpObj = smtplib.SMTP()
        # 连接到服务器
        smtpObj.connect(mail_host, 25)
        # 登录到服务器
        smtpObj.login(mail_user, mail_pass)
        # 发送
        smtpObj.sendmail(
            sender, receivers, message.as_string())
        # 退出
        smtpObj.quit()
        logger.info(f'Mail sent {title} successfully')
    except smtplib.SMTPException as e:
        logger.error('error', e)  # 打印错误


def check_memory_alarm(mem):
    logger.info('check_memory_alarm start')
    while True:
        # 内存利用率大于80%发送告警邮件
        if int(mem.percent) > 80:
            content = f'<br/>Current time:{current_time} </br> <br/>Memory utilization exceeds 80%</br>'
            mail_sender('memory warning', content)
            break
        time.sleep(5)


# cpu告警模块
def check_cpu_alarm(cpu):
    logger.info('check_cpu_alarm start')
    while True:
        # cpu利用率大于80%发送告警邮件
        if int(cpu) > 80:
            content = f'<br/>Current time:{current_time} </br> <br/>CPU utilization exceeds 80%</br>'
            mail_sender('cpu warning', content)
            break
        time.sleep(5)


def main():
    mem = psutil.virtual_memory()
    cpu = psutil.cpu_percent(interval=1)
    gevent.joinall(
        [
            gevent.spawn(print_system_info, mem, cpu),
            gevent.spawn(check_memory_alarm, mem),
            gevent.spawn(check_cpu_alarm, cpu),
            gevent.spawn(system_sender)
        ]
    )


if __name__ == '__main__':
    main()

四、未解决问题

  1. 发送邮件后,没有处理报警的能力,后续的话尝试加入自动处理报警的能力