如何避免监控test.service的脚本重复发送相同告警邮件?
问题描述
脚本内容
#!/bin/bash msg=$(find /home/testaccount/test.log -mmin -30 -exec grep test.service {} \; | tail -1) test -n "$msg" && echo "$msg" | mail -r 'database@alert.etc' -s 'Database Alert' test@gmail.com
编写了上述Bash脚本,当/home/testaccount/test.log日志文件中出现包含test.service的日志条目时,会向指定邮箱发送邮件。已将该脚本配置为通过Cron每30分钟执行一次,但目前存在问题:脚本每隔30分钟会重复发送同一条日志邮件。需要实现仅在检测到新的包含test.service的告警日志时才发送邮件,避免重复发送相同内容。
解决方案
核心逻辑是记录已发送过的日志标识,每次执行时对比最新日志是否已发送,未发送则触发邮件。
方法一:跟踪已发送的日志内容
新增一个状态文件存储最后一次发送的日志内容,每次执行脚本时对比:
#!/bin/bash # 定义路径变量 LOG_FILE="/home/testaccount/test.log" STATE_FILE="/var/log/test_service_alert_last_sent.log" # 提取最近30分钟内包含test.service的最后一条日志 latest_msg=$(find "$LOG_FILE" -mmin -30 -exec grep "test.service" {} \; | tail -1) # 无目标日志则退出 if [ -z "$latest_msg" ]; then exit 0 fi # 检查状态文件是否存在,或内容与最新日志不一致则发送邮件并更新状态 if [ ! -f "$STATE_FILE" ] || [ "$(cat "$STATE_FILE")" != "$latest_msg" ]; then echo "$latest_msg" | mail -r 'database@alert.etc' -s 'Database Alert' test@gmail.com echo "$latest_msg" > "$STATE_FILE" fi
方法二:跟踪日志行号(适配重复内容的告警)
如果日志中可能出现相同内容的新告警,改用行号跟踪更准确:
#!/bin/bash LOG_FILE="/home/testaccount/test.log" STATE_FILE="/var/log/test_service_alert_last_line.log" # 获取包含test.service的最后一行(带行号) latest_line=$(grep -n "test.service" "$LOG_FILE" | tail -1) # 无目标日志则退出 if [ -z "$latest_line" ]; then exit 0 fi # 拆分行号和日志内容 latest_line_num=$(echo "$latest_line" | cut -d: -f1) latest_msg=$(echo "$latest_line" | cut -d: -f2-) # 读取上次发送的行号,默认0 last_sent_num=$(cat "$STATE_FILE" 2>/dev/null || echo 0) # 最新行号大于上次发送的行号则触发邮件并更新状态 if [ "$latest_line_num" -gt "$last_sent_num" ]; then echo "$latest_msg" | mail -r 'database@alert.etc' -s 'Database Alert' test@gmail.com echo "$latest_line_num" > "$STATE_FILE" fi
注意事项
- 确保脚本执行用户对状态文件所在目录有写入权限,比如把状态文件放在
/home/testaccount/下(如果用的是该用户执行Cron) - 定期清理状态文件(如果需要),避免无意义的存储占用
内容的提问来源于stack exchange,提问作者manwithamission
相关产品推荐
相关产品推荐

