【日志监控方案】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 钉钉告警

相关推荐
工程师老罗7 小时前
Pytorch中的优化器及其用法
人工智能·pytorch·python
2301_822365037 小时前
实战:用Python分析某电商销售数据
jvm·数据库·python
luoluoal7 小时前
基于python的人脸识别的酒店客房入侵检测系统(源码+文档)
python·mysql·django·毕业设计·源码
子午8 小时前
【2026计算机毕设~AI项目】鸟类识别系统~Python+深度学习+人工智能+图像识别+算法模型
图像处理·人工智能·python·深度学习
流㶡8 小时前
网络爬虫库与robots.txt规则
python·网络爬虫
2301_788756068 小时前
Python在2024年的主要趋势与发展方向
jvm·数据库·python
阿部多瑞 ABU8 小时前
`tredomb`:一个面向「思想临界质量」初始化的 Python 工具
前端·python·ai写作
u0109272718 小时前
Python虚拟环境(venv)完全指南:隔离项目依赖
jvm·数据库·python
m0_686041618 小时前
Python类型提示(Type Hints)详解
jvm·数据库·python
矢志航天的阿洪8 小时前
从GitHub到本地:Python IGRF库环境配置完全指南
开发语言·python·github