python实现linux阈值检测与企微报警

阈值检测与企微报警

1、任务背景 生产环境中,单一的基础资源监控已无法满足高并发场景下的稳定性要求。为了精准定位系统瓶颈,需要构建一套覆盖资源饱和度(CPU/内存/磁盘)+ 系统压力(Load Average)+ 网络吞吐(Network I/O)”的全链路健康监测体系。通过设定多维度的安全水位阈值(如 Load > 5.0 或 CPU > 80%),在任一关键指标异常时通过企业微信实时报警,并自动归档故障现场数据

2、任务拆解
全栈指标采集:利用 psutil 库同步采集服务器的五大核心指标:CPU 使用率、内存占用、磁盘空间、系统平均负载(1分钟/5分钟)以及网络实时速率(上传/下载),形成完整的服务器健康画像。

复合阈值判定:当满足以下任一条件时判定为异常:

资源饱和:CPU > 80% 或 内存 > 90% 或 磁盘 > 85%;

系统阻塞:系统 1 分钟平均负载 > 预设阈值(如 5.0);

网络拥塞:网络流量出现持续异常高吞吐。

告警与日志审计:一旦检测到异常,立即触发企业微信 Webhook 接口推送包含具体故障指标的告警信息,同步将故障发生时的所有资源快照写入本地日志,为后续的根因分析(RCA)提供数据支撑。

企微接口文档:https://developer.work.weixin.qq.com/document/path/91770

3、代码实现

点击查看代码
# 导入相关模块
import psutil
import time
import requests
from datetime import datetime

LOG_FILE = 'resource_alert.log'

# 定义阈值 以及 企业告警链接地址
CPU_THRESHOLD = 80
MEMORY_THRESHOLD = 90
DISK_THRESHOLD = 85
# 系统负载阈值 (例如 4核CPU 建议设为 4.0 或 5.0)
LOAD_THRESHOLD = 5.0 
#修改为你的企业微信接口
WEBHOOK_URL = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='

# 日志记录函数
def log_alert(resource_type, usage, threshold):
    # 获取当前时间
    current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    
    # 格式化日志信息
    message = f'[{current_time}] {resource_type}使用率过高,超过了阈值{threshold},当前数值为{usage}\n'
    
    # 打开文件并写入日志
    with open(LOG_FILE, 'a', encoding='utf-8') as file:
        file.write(message)
    
    print(f"!!! 触发告警: {message.strip()}")

def send_wechat_alert(message):
    # 定义header头信息
    headers = {'Content-Type': 'application/json'}
    
    # 定义传输数据
    data = {
        "msgtype": "text",
        "text": {
            "content": f"【服务器监控告警】\n{message}"
        }
    }
    
    try:
        response = requests.post(url=WEBHOOK_URL, headers=headers, json=data)
        if response.status_code == 200:
            print('告警发送成功!')
        else:
            print(f'告警发送失败,状态码: {response.status_code}')
    except Exception as e:
        print(f'企业微信接口调用失败,错误信息为:{e}')

def get_network_speed(interval=1):
    """
    计算网络速率 (KB/s),同时利用这段等待时间获取CPU使用率
    """
    # 1. 获取初始网络计数
    net_before = psutil.net_io_counters()
    
    # 2. 获取CPU使用率 (这里会阻塞 interval 秒)
    cpu_usage = psutil.cpu_percent(interval=interval)
    
    # 3. 获取结束网络计数
    net_after = psutil.net_io_counters()

    # 4. 计算速率 (字节 -> KB)
    sent_speed = (net_after.bytes_sent - net_before.bytes_sent) / 1024 / interval
    recv_speed = (net_after.bytes_recv - net_before.bytes_recv) / 1024 / interval
    
    return cpu_usage, sent_speed, recv_speed

def check_resource_usage():
    # 1. 获取 CPU 和 网络速率 (耗时1秒)
    cpu_usage, sent_speed, recv_speed = get_network_speed(interval=1)
    
    # 2. 获取内存使用率
    memory_usage = psutil.virtual_memory().percent
    
    # 3. 获取磁盘使用率
    disk_usage = psutil.disk_usage('/').percent

    # 4. 获取系统负载 (新增)
    # getloadavg() 返回 (1分钟, 5分钟, 15分钟) 的负载元组
    try:
        load_avg = psutil.getloadavg()
        load_1min = load_avg[0]
    except AttributeError:
        # Windows 系统可能不支持 getloadavg,做个兼容处理
        load_1min = 0.0

    # ================= 打印当前状态 (包含网络和Load) =================
    print(f'资源监控 -> CPU:{cpu_usage}% | 内存:{memory_usage}% | 磁盘:{disk_usage}% | Load(1m):{load_1min:.2f}')
    print(f'网络流量 -> 上传: {sent_speed:.2f} KB/s | 下载: {recv_speed:.2f} KB/s')
    print('-' * 50)

    # ================= 告警逻辑判断 =================
    
    # CPU 判断
    if cpu_usage > CPU_THRESHOLD:
        log_alert('CPU', f"{cpu_usage}%", f"{CPU_THRESHOLD}%")
        send_wechat_alert(f'CPU使用率过高!\n当前: {cpu_usage}%\n阈值: {CPU_THRESHOLD}%')
    
    # 内存 判断
    if memory_usage > MEMORY_THRESHOLD:
        log_alert('内存', f"{memory_usage}%", f"{MEMORY_THRESHOLD}%")
        send_wechat_alert(f'内存使用率过高!\n当前: {memory_usage}%\n阈值: {MEMORY_THRESHOLD}%')
    
    # 磁盘 判断
    if disk_usage > DISK_THRESHOLD:
        log_alert('磁盘', f"{disk_usage}%", f"{DISK_THRESHOLD}%")
        send_wechat_alert(f'磁盘使用率过高!\n当前: {disk_usage}%\n阈值: {DISK_THRESHOLD}%')

    # 系统负载 判断 
    if load_1min > LOAD_THRESHOLD:
        log_alert('系统负载(Load 1min)', load_1min, LOAD_THRESHOLD)
        send_wechat_alert(f'系统负载过高!\n当前1分钟负载: {load_1min}\n阈值: {LOAD_THRESHOLD}')

if __name__ == '__main__':
    try:
        print('开始全维度监控系统资源 (CPU/内存/磁盘/负载/网络)...(按Ctrl+C停止)')
        while True:
            check_resource_usage()
            # 这里的sleep可以适当缩短,因为 get_network_speed 已经阻塞了1秒
            time.sleep(4) 
    except KeyboardInterrupt:
        print('\n监控已手动停止!')

posted @ 2026-01-01 23:23  chenwenjie灬  阅读(0)  评论(0)    收藏  举报