以下是一个用于监测Nginx访问日志中502状态码(Bad Gateway)的Shell脚本,当检测到指定阈值时触发告警或自动恢复操作,并提供详细注释和扩展建议:
脚本功能
1、实时监控Nginx访问日志中的502错误
2、支持自定义检测阈值(例如:1分钟内出现5次502则告警)
3、触发动作:邮件通知、服务重启、自定义恢复脚本
4、自动记录检测结果到日志文件
脚本代码
#!/bin/bash
# Nginx 502错误监控脚本
# 配置参数
LOG_FILE="/var/log/nginx/access.log" # Nginx日志路径
ERROR_CODE="502" # 监控的状态码
THRESHOLD=5 # 触发动作的阈值(次数)
TIME_WINDOW=60 # 检测时间窗口(秒)
ALERT_EMAIL="admin@example.com" # 告警通知邮箱
NGINX_RESTART_CMD="systemctl restart nginx" # Nginx重启命令
# 临时存储检测结果
TMP_FILE="/tmp/nginx_502_monitor.tmp"
# 日志记录函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> /var/log/nginx_502_monitor.log
}
# 核心检测逻辑
detect_502() {
# 获取最近TIME_WINDOW秒内的502错误数量
count=$(tail -n 1000 "$LOG_FILE" | awk -v code="$ERROR_CODE" -v now=$(date +%s) '
{
# 解析日志时间(假设日志时间格式为[05/Oct/2023:14:30:22 +0800])
gsub(/\[/, "", $4);
timestamp = mktime(gensub(":", " ", "g", substr($4, 1, 20)));
if (now - timestamp <= '$TIME_WINDOW' && $9 == code) {
count++
}
} END { print count }'
)
# 判断是否超过阈值
if [ "$count" -ge "$THRESHOLD" ]; then
log "检测到502错误次数: $count (阈值: $THRESHOLD)"
return 0 # 满足条件
else
return 1 # 未满足条件
fi
}
# 触发动作
take_action() {
# 1. 发送邮件告警
echo "Nginx 502错误告警:
- 时间: $(date)
- 错误次数: $count
- 日志片段:
$(grep " $ERROR_CODE " "$LOG_FILE" | tail -n 3)" | mail -s "Nginx 502告警" "$ALERT_EMAIL"
# 2. 自动重启Nginx(可选)
# $NGINX_RESTART_CMD && log "Nginx已重启"
# 3. 执行自定义恢复脚本(示例)
# /path/to/recovery_script.sh
}
# 主循环(实时监控模式)
monitor() {
log "开始监控502错误..."
tail -F "$LOG_FILE" | while read line; do
if echo "$line" | awk '$9 == '"$ERROR_CODE"' { exit 0 }'; then
echo "$line" >> "$TMP_FILE"
current_count=$(wc -l < "$TMP_FILE")
if [ "$current_count" -ge "$THRESHOLD" ]; then
take_action
> "$TMP_FILE" # 清空临时计数器
sleep 300 # 冷却时间(避免重复告警)
fi
fi
done
}
# 执行检测(定期模式)
# 使用crontab每1分钟运行一次:*/1 * * * * /path/to/script.sh
periodic_check() {
if detect_502; then
take_action
fi
}
# 选择模式:实时监控(monitor)或定期检测(periodic_check)
# monitor
periodic_check
使用说明
1、配置参数
修改 LOG_FILE 为你的Nginx访问日志路径
调整 THRESHOLD 和 TIME_WINDOW 设置触发阈值(例如:60秒内5次502错误)
填写 ALERT_EMAIL 接收告警的邮箱
2、运行模式
实时监控:执行 monitor 函数(需手动运行脚本或配置为后台服务)
定期检测:执行 periodic_check 函数并通过crontab定时运行(推荐)
3、部署到crontab
# 每5分钟检测一次
*/5 * * * * /path/to/script.sh
扩展功能
1、多日志文件支持
监控多个日志文件(如多个虚拟主机):
LOG_FILES=("/var/log/nginx/host1.access.log" "/var/log/nginx/host2.access.log")
for log in "${LOG_FILES[@]}"; do
count+=$(分析逻辑)
done
2、集成告警平台
替换邮件通知为钉钉/企业微信机器人:
# 钉钉机器人示例
DING_WEBHOOK="https://oapi.dingtalk.com/robot/send?access_token=xxx"
curl -s "$DING_WEBHOOK" -H 'Content-Type: application/json' -d "{
'msgtype': 'text',
'text': {'content': 'Nginx 502告警: 错误次数 $count'}
}"
3、自动故障转移
当持续出现502时,切换上游服务器:
# 修改Nginx配置中的上游服务器
sed -i 's/server bad-backend:80/server good-backend:80/' /etc/nginx/upstream.conf
nginx -s reload
注意事项
1、日志时间格式
脚本假设日志时间格式为 [05/Oct/2023:14:30:22 +0800],如使用其他格式需调整 gensub 部分。
2、性能优化
对于高流量网站,避免使用 tail -F 实时监控,改用定期分析。
使用 logrotate 管理日志文件大小。
3、权限配置
确保脚本有权限读取Nginx日志文件。
若需要重启服务,配置sudo权限:
# 在/etc/sudoers中添加
your_user ALL=(ALL) NOPASSWD: /bin/systemctl restart nginx
4、测试验证
手动生成502错误测试脚本:
# 快速生成测试日志(需临时修改Nginx返回502)
echo '127.0.0.1 - - [05/Oct/2023:15:00:00 +0800] "GET / HTTP/1.1" 502 572 "-" "curl/7.68.0"' >> $LOG_FILE
通过此脚本,您可以快速搭建Nginx 502错误监控系统,及时发现问题并触发告警或自动恢复,保障服务可用性。