服务器定时发送邮件设置

服务器定时发送邮件设置

crontab -e

bash 复制代码
"/tmp/crontab.srYPTQ" 1L, 72B
*/10 * * * * /usr/bin/python3 /root/send_mail.py >> /root/mail.log 2>&1

检查日志,并发送邮件

python 复制代码
import os
import re
import smtplib
from datetime import datetime, date
from email.mime.text import MIMEText
from email.header import Header

# ========== 日志监控配置 ==========
LOG_FILE = "/root/xxx.log"
KEYWORD = "youtube"
STATE_FILE = "/root/mail_auto/log_monitor.state"

# ========== QQ邮箱配置 ==========
SMTP_HOST = "smtp.qq.com"
SMTP_PORT = 465

SENDER = "你的QQ邮箱@qq.com"
AUTH_CODE = "你的QQ邮箱授权码"
RECEIVER = "接收报警的邮箱@example.com"


def send_email(subject, body):
    msg = MIMEText(body, "plain", "utf-8")
    msg["From"] = SENDER
    msg["To"] = RECEIVER
    msg["Subject"] = Header(subject, "utf-8")

    with smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT) as server:
        server.login(SENDER, AUTH_CODE)
        server.sendmail(SENDER, [RECEIVER], msg.as_string())


def get_last_position():
    if not os.path.exists(STATE_FILE):
        return None

    try:
        with open(STATE_FILE, "r") as f:
            return int(f.read().strip())
    except Exception:
        return None


def save_position(position):
    with open(STATE_FILE, "w") as f:
        f.write(str(position))


def parse_log_time(line):
    """
    匹配日志时间格式:
    2026/05/03 14:20:00
    """

    pattern = r"(\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2})"
    match = re.search(pattern, line)

    if not match:
        return None

    try:
        return datetime.strptime(match.group(1), "%Y/%m/%d %H:%M:%S")
    except Exception:
        return None


def filter_today_lines(content):
    today = date.today()

    today_lines = []
    for line in content.splitlines():
        log_time = parse_log_time(line)

        if log_time is not None and log_time.date() == today:
            today_lines.append(line)

    return "\n".join(today_lines)


def monitor_log():
    if not os.path.exists(LOG_FILE):
        print(f"日志文件不存在: {LOG_FILE}")
        return

    current_size = os.path.getsize(LOG_FILE)
    last_position = get_last_position()

    with open(LOG_FILE, "r", encoding="utf-8", errors="ignore") as f:
        if last_position is None:
            # 首次运行:读取整个日志,但只检查今天的内容
            print("首次运行:只检查今天的日志")
            content = f.read()
            check_content = filter_today_lines(content)
        else:
            # 如果日志被清空或轮转,从头开始
            if current_size < last_position:
                last_position = 0

            f.seek(last_position)
            content = f.read()

            # 后续运行:只检查新增内容,并且只保留今天的日志
            check_content = filter_today_lines(content)

        new_position = f.tell()

    # 无论是否命中,都保存当前位置,避免重复检查
    save_position(new_position)

    if KEYWORD.lower() in check_content.lower():
        matched_lines = []
        for line in check_content.splitlines():
            if KEYWORD.lower() in line.lower():
                matched_lines.append(line)

        matched_text = "\n".join(matched_lines[:20])

        subject = f"服务器日志报警:检测到关键词 {KEYWORD}"
        body = f"""
检测到日志中出现关键词:{KEYWORD}

日志文件:
{LOG_FILE}

匹配关键词:
{KEYWORD}

匹配到的日志如下:

{matched_text}
"""

        send_email(subject, body)
        print(f"检测到关键词 {KEYWORD},已发送邮件")
    else:
        print(f"今天的新增日志中未检测到关键词 {KEYWORD}")


if __name__ == "__main__":
    monitor_log()
相关推荐
雷工笔记1 小时前
MES 系统设备管理模块详细设计方案
大数据·运维·网络
wangchunting1 小时前
VMware17 使用Rocky Linux 9.7系统
linux·运维·服务器
我不是立达刘宁宇2 小时前
基础文件操作
运维
青梅橘子皮2 小时前
Linux---权限
linux·运维·服务器
Jul1en_3 小时前
Claude 迁移 Codex 工作流迁移与更新
java·服务器·前端·后端·ai编程
gQ85v10Db3 小时前
Redis分布式锁进阶第十五篇:全系列终极收官复盘 + 全站锁规范归档 + 生产零故障长期运维兜底总方案
运维·redis·分布式
智能化咨询3 小时前
(112页PPT)德勤制造业企业数据治理平台规划方案(附下载方式)
大数据·运维·人工智能
时光之源4 小时前
安装WSL2后在其中安装Ubuntu24.04.4再安装OpenClaw全流程傻瓜式教学:WSL2 + Ubuntu 24.04 + OpenClaw
linux·运维·ubuntu·openclaw·龙虾
eastyuxiao4 小时前
流程图 + 配置清单 在团队 / 公司项目管理场景的落地应用
大数据·运维·人工智能·流程图