服务器定时发送邮件设置
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()