You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

日志监控脚本重复发送邮件问题解决及服务化功能优化咨询

刚好遇到过类似的日志监控告警重复触发的问题,我来帮你一步步解决邮件轰炸的问题,同时实现你需要的重启服务和后台持续监控功能:

解决日志监控脚本重复发邮件及扩展功能的方案

一、先搞定邮件轰炸的问题

你的脚本现在每抓到一行带error的日志就发一次邮件,碰到批量错误日志直接就炸邮箱了。咱们可以通过记录已处理的错误标识来避免重复触发,这里给你两种实用方案:

方案1:基于错误行哈希去重

这个思路是给每一行错误日志生成唯一的MD5哈希值,记录最后一次发邮件对应的哈希,只有新错误的哈希和记录的不一样时才触发邮件,适合区分不同类型的错误:

#!/bin/bash
# 用来存最后一次错误哈希的临时文件
LAST_ERROR_HASH_FILE="/tmp/monitor_last_error_hash"

# 用tail -F替代tail -f,自动处理日志轮转(syslog切文件后也能继续监控)
tail -Fn0 /var/log/syslog | while read line ; do
    # 检测是否包含error(忽略大小写)
    if echo "${line}" | grep -qi "error"; then
        # 给当前错误行生成哈希值
        current_hash=$(echo "${line}" | md5sum | awk '{print $1}')
        # 读取上次记录的哈希(文件不存在就返回空)
        last_hash=$(cat "${LAST_ERROR_HASH_FILE}" 2>/dev/null || echo "")
        
        # 哈希不一样才发邮件,然后更新记录
        if [ "${current_hash}" != "${last_hash}" ]; then
            python emailsend.py
            echo "${current_hash}" > "${LAST_ERROR_HASH_FILE}"
            # 后面加重启服务的命令,先留个位置
            # systemctl restart your-target-service.service
        fi
    fi
done

方案2:设置冷却时间(短时间内只发一次)

如果同一错误反复刷屏,你可能希望比如10分钟内只发一次告警,避免邮箱被刷爆,这种情况用冷却时间更合适:

#!/bin/bash
# 存最后一次发邮件时间戳的文件
LAST_SEND_TIME_FILE="/tmp/monitor_last_send_time"
# 冷却时间设为10分钟(600秒,你可以自己调)
COOLDOWN=600

tail -Fn0 /var/log/syslog | while read line ; do
    if echo "${line}" | grep -qi "error"; then
        # 获取当前时间戳(秒)
        current_time=$(date +%s)
        # 读取上次发邮件的时间,默认0表示从未发过
        last_time=$(cat "${LAST_SEND_TIME_FILE}" 2>/dev/null || echo 0)
        
        # 间隔超过冷却时间才发邮件
        if [ $((current_time - last_time)) -gt $COOLDOWN ]; then
            python emailsend.py
            echo "${current_time}" > "${LAST_SEND_TIME_FILE}"
            # 重启服务的命令写在这
            # systemctl restart your-target-service.service
        fi
    fi
done

二、添加重启服务功能

发完邮件后直接加重启服务的命令就行,注意两点:

  • 脚本最好用root用户运行,确保有权限重启服务;如果用普通用户,得给脚本配置sudo免密
  • your-target-service.service换成你实际要重启的服务名(比如nginx.serviceapache2.service

举个例子:

# 发邮件后更新记录,然后重启服务
python emailsend.py
echo "${current_hash}" > "${LAST_ERROR_HASH_FILE}"
sudo systemctl restart nginx.service

三、把脚本做成systemd服务,实现后台持续监控

要让脚本开机自动启动、崩溃了自动重启,还能处理日志轮转,做成systemd服务是最优解:

  1. 创建服务文件/etc/systemd/system/log-monitor.service,内容如下:
[Unit]
Description=Syslog Error Monitor & Alert Service
After=network.target  # 等网络起来再启动,确保能发邮件

[Service]
Type=simple
ExecStart=/usr/local/bin/monitor.bash  # 你的脚本路径
Restart=always  # 崩溃了自动重启
RestartSec=5  # 崩溃后5秒重启
User=root  # 用root运行,权限足够

[Install]
WantedBy=multi-user.target  # 多用户模式下开机自启
  1. 重新加载systemd配置,启动并设置开机自启:
sudo systemctl daemon-reload
sudo systemctl start log-monitor.service
sudo systemctl enable log-monitor.service
  1. 可以用下面的命令查看服务状态,确认是否正常运行:
sudo systemctl status log-monitor.service

这样配置后,就算syslog日志轮转(比如被logrotate切分),因为我们用了tail -F,脚本会自动切换到新的日志文件继续监控,完全不用操心。


内容的提问来源于stack exchange,提问作者Dybbuk

火山引擎 最新活动