Shell脚本中实现信号量机制以避免同一问题重复发送告警
嘿,这个重复告警的问题我太熟了!很多人写监控脚本都会踩这个坑——只要阈值还超标就不停发邮件,邮箱直接炸掉对吧?其实用个简单的锁文件当信号量就能完美解决,下面给你一套落地性极强的方案:
用信号量(锁文件)阻止重复告警的Shell脚本方案
核心逻辑
本质就是用一个临时文件作为"告警标记":
- 首次触发告警时,发送邮件并创建这个标记文件
- 后续检测到阈值超标但标记存在时,直接跳过邮件发送
- 当警告数回落至正常范围,立刻删除标记,恢复告警能力
完整可运行脚本示例
#!/bin/bash # -------------------------- 配置区 -------------------------- LOG_FILE="/var/log/your_app.log" # 要监控的日志文件路径 WARNING_THRESHOLD=10 # 警告数量阈值 ALERT_EMAIL="ops_team@your_company.com"# 告警接收邮箱 LOCK_FILE="/tmp/app_warning_alert.lock"# 信号量锁文件路径 # ----------------------------------------------------------- # 统计日志中的警告数量(这里假设日志行含"WARNING"关键词,可按需修改) warning_count=$(grep -c "WARNING" "$LOG_FILE") # 先处理锁文件超时问题(防止脚本意外中断导致永久锁死) if [ -f "$LOCK_FILE" ]; then # 计算锁文件存在时长(单位:秒),超过24小时自动清除 lock_exist_time=$(( $(date +%s) - $(stat -c %Y "$LOCK_FILE") )) if [ "$lock_exist_time" -gt 86400 ]; then rm -f "$LOCK_FILE" echo "$(date +'%Y-%m-%d %H:%M:%S') - 锁文件已超时,自动清除" fi fi # 核心告警逻辑 if [ "$warning_count" -gt "$WARNING_THRESHOLD" ]; then if [ ! -f "$LOCK_FILE" ]; then # 发送告警邮件(这里用mail命令,可替换为sendmail或第三方邮件API) echo "系统告警:日志中警告数量超标!当前数量:$warning_count 日志路径:$LOG_FILE 阈值:$WARNING_THRESHOLD" | mail -s "【紧急告警】应用警告数量超出阈值" "$ALERT_EMAIL" # 创建锁文件标记已告警 touch "$LOCK_FILE" echo "$(date +'%Y-%m-%d %H:%M:%S') - 警告数量超标,已发送告警并创建锁文件" else echo "$(date +'%Y-%m-%d %H:%M:%S') - 警告数量仍超标,但已发送过告警,跳过重复通知" fi else # 警告数恢复正常,清除锁文件 if [ -f "$LOCK_FILE" ]; then rm -f "$LOCK_FILE" echo "$(date +'%Y-%m-%d %H:%M:%S') - 警告数量恢复正常,已清除锁文件" fi echo "$(date +'%Y-%m-%d %H:%M:%S') - 警告数量在阈值范围内,无需处理" fi
关键细节说明
- 锁文件位置:选
/tmp目录很合适,系统重启后会自动清理,避免遗留无效锁 - 日志统计适配:如果你的日志格式特殊(比如需要按时间段统计),可以把
grep -c "WARNING"换成awk或者sed的复杂过滤逻辑 - 死锁防护:加了24小时超时清除逻辑,就算脚本意外崩溃,也不会永久无法触发新告警
- 多指标扩展:如果要监控多个告警项,给每个项单独建锁文件即可(比如
/tmp/alert_lock_error.tmp)
部署建议
把脚本放到服务器上,用cron定时执行(比如每分钟跑一次):
# 编辑crontab crontab -e # 添加一行 * * * * * /path/to/your/alert_script.sh >> /var/log/alert_script_run.log 2>&1
内容的提问来源于stack exchange,提问作者sangavis




