【日志监控方案】Python脚本获取关键字日志信息并推送钉钉告警

目录

[1. 完整脚本](#1. 完整脚本)

[2. 使用说明](#2. 使用说明)

[2.1 前置准备](#2.1 前置准备)

[2.2 安装依赖](#2.2 安装依赖)

[2.3 配置修改](#2.3 配置修改)

[2.4 运行脚本](#2.4 运行脚本)

[2.5 后台运行(生产环境推荐)](#2.5 后台运行(生产环境推荐))

[2.6 告警测试](#2.6 告警测试)

[2.6.1 执行脚本](#2.6.1 执行脚本)

[2.6.2 触发告警](#2.6.2 触发告警)

[2.6.3 钉钉告警](#2.6.3 钉钉告警)


1. 完整脚本

下面是一个完整的Python脚本方案,用于实时监控服务器日志并通过钉钉发送告警。这个方案结合了实时日志跟踪、关键字匹配和钉钉消息推送功能。

cat python_log_monitor.sh

复制代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import re
import time
import requests
import json
import os
from datetime import datetime
from typing import List, Dict

class LogMonitor:
    def __init__(self, log_file: str, keywords: List[str], dingding_webhook: str,
                 check_interval: int = 2, max_message_length: int = 2000):
        """
        初始化日志监控器

        Args:
            log_file: 要监控的日志文件路径
            keywords: 监控的关键字列表
            dingding_webhook: 钉钉机器人Webhook地址
            check_interval: 检查间隔(秒)
            max_message_length: 消息最大长度(钉钉限制)
        """
        self.log_file = log_file
        self.keywords = keywords
        self.dingding_webhook = dingding_webhook
        self.check_interval = check_interval
        self.max_message_length = max_message_length
        self.last_position = 0
        self.keyword_pattern = re.compile('|'.join(keywords), re.IGNORECASE)

        # 验证文件存在性
        if not os.path.exists(log_file):
            raise FileNotFoundError(f"日志文件不存在: {log_file}")

    def tail_log(self) -> List[str]:
        """实时读取日志文件的新内容"""
        new_lines = []

        try:
            with open(self.log_file, 'r', encoding='utf-8', errors='ignore') as f:
                # 移动到文件末尾
                f.seek(0, 2)
                current_size = f.tell()

                # 如果文件被截断或重新创建,重置位置
                if current_size < self.last_position:
                    self.last_position = 0

                # 读取新内容
                if current_size > self.last_position:
                    f.seek(self.last_position)
                    new_lines = f.readlines()
                    self.last_position = f.tell()

        except Exception as e:
            print(f"读取日志文件错误: {e}")
            # 发生错误时重置文件指针
            self.last_position = 0

        return new_lines

    def contains_keyword(self, line: str) -> bool:
        """检查行是否包含关键字"""
        return bool(self.keyword_pattern.search(line))

    def send_dingding_alert(self, log_line: str, matched_keyword: str):
        """发送钉钉告警消息"""
        # 截断过长的消息
        if len(log_line) > self.max_message_length:
            log_line = log_line[:self.max_message_length] + "..."

        # 构建Markdown格式消息
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        hostname = os.uname().nodename if hasattr(os, 'uname') else "Unknown"

        markdown_content = f"""## 🔴 日志监控告警
**⏰ 时间**: {timestamp}
**🖥️ 服务器**: {hostname}
**📁 文件**: {self.log_file}
**🔍 关键字**: `{matched_keyword}`
**📋 日志内容**:
{log_line.strip()}
请及时检查处理。"""

        # 构建请求数据
        data = {
            "msgtype": "markdown",
            "markdown": {
                "title": "日志监控告警",
                "text": markdown_content
            },
            "at": {
                "isAtAll": False
            }
        }

        try:
            headers = {'Content-Type': 'application/json'}
            response = requests.post(
                self.dingding_webhook,
                data=json.dumps(data),
                headers=headers,
                timeout=10
            )

            if response.status_code == 200:
                print(f"{timestamp} - 告警发送成功")
            else:
                print(f"{timestamp} - 告警发送失败: {response.status_code} - {response.text}")

        except Exception as e:
            print(f"{timestamp} - 发送钉钉消息异常: {e}")

    def start_monitoring(self):
        """开始监控日志文件"""
        print(f"开始监控日志文件: {self.log_file}")
        print(f"监控关键字: {', '.join(self.keywords)}")
        print("监控已启动,按 Ctrl+C 停止...")

        try:
            # 初始化文件指针到文件末尾
            with open(self.log_file, 'r', encoding='utf-8', errors='ignore') as f:
                f.seek(0, 2)
                self.last_position = f.tell()

            while True:
                new_lines = self.tail_log()

                for line in new_lines:
                    if self.contains_keyword(line):
                        matched_keyword = self.keyword_pattern.search(line).group()
                        print(f"检测到关键字 '{matched_keyword}': {line.strip()}")
                        self.send_dingding_alert(line, matched_keyword)

                time.sleep(self.check_interval)

        except KeyboardInterrupt:
            print("\n监控已停止")
        except Exception as e:
            print(f"监控异常: {e}")

# 配置区域 - 请根据实际情况修改
CONFIG = {
    "log_file": "/home/wwwlogs/access.log",  # 监控的日志文件路径
    "keywords": ["ERROR", "Exception", "Failed", "500", "503"],  # 监控的关键字
    "dingding_webhook": "https://oapi.dingtalk.com/robot/send?access_token=c99999999999999999999999b68c729ef88888888888888",  # 钉钉Webhook
    "check_interval": 2  # 检查间隔(秒)
}

def main():
    """主函数"""
    try:
        monitor = LogMonitor(
            log_file=CONFIG["log_file"],
            keywords=CONFIG["keywords"],
            dingding_webhook=CONFIG["dingding_webhook"],
            check_interval=CONFIG["check_interval"]
        )
        monitor.start_monitoring()

    except Exception as e:
        print(f"启动监控失败: {e}")

if __name__ == "__main__":
    main()

2. 使用说明

2.1 前置准备

创建钉钉机器人获取Webhook地址中的access_token

2.2 安装依赖

复制代码
pip install requests

2.3 配置修改

修改脚本末尾的CONFIG字典:

  • log_file: 改为你要监控的实际日志文件路径

  • keywords: 根据你的需求调整监控关键字

  • dingding_webhook: 替换为你的钉钉机器人Webhook地址

2.4 运行脚本

复制代码
python3 log_monitor.py

2.5 后台运行(生产环境推荐)

复制代码
nohup python3 log_monitor.py > monitor.log 2>&1 &

2.6 告警测试

2.6.1 执行脚本

2.6.2 触发告警

2.6.3 钉钉告警

相关推荐
玄同7659 小时前
从 0 到 1:用 Python 开发 MCP 工具,让 AI 智能体拥有 “超能力”
开发语言·人工智能·python·agent·ai编程·mcp·trae
小瑞瑞acd9 小时前
【小瑞瑞精讲】卷积神经网络(CNN):从入门到精通,计算机如何“看”懂世界?
人工智能·python·深度学习·神经网络·机器学习
火车叼位10 小时前
也许你不需要创建.venv, 此规范使python脚本自备依赖
python
火车叼位10 小时前
脚本伪装:让 Python 与 Node.js 像原生 Shell 命令一样运行
运维·javascript·python
孤狼warrior10 小时前
YOLO目标检测 一千字解析yolo最初的摸样 模型下载,数据集构建及模型训练代码
人工智能·python·深度学习·算法·yolo·目标检测·目标跟踪
Katecat9966310 小时前
YOLO11分割算法实现甲状腺超声病灶自动检测与定位_DWR方法应用
python
玩大数据的龙威10 小时前
农经权二轮延包—各种地块示意图
python·arcgis
ZH154558913111 小时前
Flutter for OpenHarmony Python学习助手实战:数据库操作与管理的实现
python·学习·flutter
belldeep11 小时前
python:用 Flask 3 , mistune 2 和 mermaid.min.js 10.9 来实现 Markdown 中 mermaid 图表的渲染
javascript·python·flask
喵手11 小时前
Python爬虫实战:电商价格监控系统 - 从定时任务到历史趋势分析的完整实战(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·零基础python爬虫教学·电商价格监控系统·从定时任务到历史趋势分析·采集结果sqlite存储