日志监控脚本重复发送邮件问题解决及服务化功能优化咨询
刚好遇到过类似的日志监控告警重复触发的问题,我来帮你一步步解决邮件轰炸的问题,同时实现你需要的重启服务和后台持续监控功能:
解决日志监控脚本重复发邮件及扩展功能的方案
一、先搞定邮件轰炸的问题
你的脚本现在每抓到一行带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.service、apache2.service)
举个例子:
# 发邮件后更新记录,然后重启服务 python emailsend.py echo "${current_hash}" > "${LAST_ERROR_HASH_FILE}" sudo systemctl restart nginx.service
三、把脚本做成systemd服务,实现后台持续监控
要让脚本开机自动启动、崩溃了自动重启,还能处理日志轮转,做成systemd服务是最优解:
- 创建服务文件
/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 # 多用户模式下开机自启
- 重新加载systemd配置,启动并设置开机自启:
sudo systemctl daemon-reload sudo systemctl start log-monitor.service sudo systemctl enable log-monitor.service
- 可以用下面的命令查看服务状态,确认是否正常运行:
sudo systemctl status log-monitor.service
这样配置后,就算syslog日志轮转(比如被logrotate切分),因为我们用了tail -F,脚本会自动切换到新的日志文件继续监控,完全不用操心。
内容的提问来源于stack exchange,提问作者Dybbuk




