2. 日志文件监控与告警
任务说明
监控指定日志文件(默认 /var/log/syslog),当新增日志行中出现错误关键字(如 ERROR、CRITICAL、Traceback)时,立即发送邮件告警。脚本需持续运行,支持自定义日志路径、关键字列表与邮件接收人。
实现思路
使用 tail -f 子进程实时跟踪文件追加内容,逐行匹配关键字;命中后通过 SMTP 发送告警邮件。采用 subprocess.Popen 而非 time.sleep 轮询,确保日志产生后毫秒级响应,且不遗漏重启期间产生的日志。
完整代码
#!/usr/bin/env python3
import subprocess
import smtplib
import sys
import re
from email.mime.text import MIMEText
from email.header import Header
# ========== 配置区 ==========
LOG_FILE = "/var/log/syslog" # 监控的日志文件
KEYWORDS = ["ERROR", "CRITICAL", "Traceback"] # 触发告警的关键字
MAIL_SMTP = "smtp.example.com" # SMTP服务器
MAIL_PORT = 465 # SSL端口
MAIL_USER = "monitor@example.com" # 发件邮箱
MAIL_PASS = "your_password" # 邮箱授权码
MAIL_TO = ["admin@example.com"] # 收件人列表
# ============================
def send_alert(line: str):
"""发送告警邮件,内容为匹配到的日志行"""
subject = f"[日志告警] {LOG_FILE} 出现异常"
body = f"时间: {__import__('time').strftime('%Y-%m-%d %H:%M:%S')}\n文件: {LOG_FILE}\n内容: {line.strip()}"
msg = MIMEText(body, "plain", "utf-8")
msg["Subject"] = Header(subject, "utf-8")
msg["From"] = MAIL_USER
msg["To"] = ", ".join(MAIL_TO)
try:
with smtplib.SMTP_SSL(MAIL_SMTP, MAIL_PORT) as server:
server.login(MAIL_USER, MAIL_PASS)
server.sendmail(MAIL_USER, MAIL_TO, msg.as_string())
print(f"[告警已发送] {line.strip()[:80]}")
except Exception as e:
print(f"[邮件发送失败] {e}", file=sys.stderr)
def main():
# 启动 tail -f 跟踪文件新增内容
proc = subprocess.Popen(
["tail", "-F", LOG_FILE],
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
universal_newlines=True,
bufsize=1
)
print(f"开始监控 {LOG_FILE},关键字: {KEYWORDS}")
# 预编译正则,忽略大小写
pattern = re.compile("|".join(map(re.escape, KEYWORDS)), re.IGNORECASE)
for raw_line in proc.stdout:
line = raw_line.rstrip("\n")
if pattern.search(line):
send_alert(line)
if __name__ == "__main__":
main()
运行与验证
- 安装依赖:仅使用 Python 3 标准库,无需 pip 安装。
- 修改配置:将
MAIL_SMTP、MAIL_USER、MAIL_PASS、MAIL_TO替换为真实邮箱信息(推荐使用 465 端口 SSL)。 - 启动监控:
sudo python3 log_monitor.py(读取 /var/log/syslog 通常需要 root 权限)。 - 模拟触发:另开终端执行
logger -p user.err "测试 ERROR 告警",该命令会向 syslog 写入一条含ERROR的新日志。 - 判定通过:脚本终端输出
[告警已发送],且收件邮箱收到标题为“日志告警”的邮件,内容包含触发行的完整信息。
常见问题
- 收不到邮件:检查 SMTP 服务器地址、端口、授权码是否正确;部分邮箱需在设置中开启 SMTP 服务并生成专用授权码。
- 监控不生效:确认脚本有日志文件读取权限;
tail -F会处理文件轮转,但若文件被删除且不再创建,进程会等待。 - 关键字误报:修改
KEYWORDS列表为精确匹配词,或改用正则表达式(如r"ERROR.*timeout")以缩小范围。