服务器定时发送邮件设置

服务器定时发送邮件设置

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()
相关推荐
隔窗听雨眠6 分钟前
Nginx网关响应慢排查手记
java·服务器·nginx
人还是要有梦想的28 分钟前
linux下用搜狗输入法,中英文切换
linux·运维·服务器
北京智和信通36 分钟前
某部队IT基础设施及机房动环统一运维建设实例
运维·网管平台·网管软件·网络管理系统·网络运维平台·网络运维系统
乐维_lwops1 小时前
从 “救火运维” 到 “自动驾驶”:运维智能体到底解决了什么?
运维·人工智能·运维智能体
bush41 小时前
嵌入式linux学习记录二
linux·运维·学习
9分钟带帽1 小时前
linux_通过NFS挂载远程服务器的硬盘
linux·服务器
weixin_468466851 小时前
MoneyPrinterTurbo 短视频自动化生产实战指南
运维·人工智能·自动化·大模型·音视频·moneyprinter
難釋懷2 小时前
Nginx自签名-图形化工具 XCA
运维·nginx
迷枫7123 小时前
DM8 目录结构与常用排查入口梳理
服务器·数据库
志栋智能3 小时前
小步快跑:从单一场景开启超自动化巡检之旅
运维·网络·人工智能·自动化