高可用巡检脚本实战:一键掌握服务、网络、VIP、资源状态
🛠️ 单位账户管理系统高可用巡检脚本实战:一键掌握服务、网络、VIP、资源状态
作者:运维小记
场景:单位账户管理系统(UAMS)
目标:构建一套全自动、可视化、高可用的服务器状态巡检方案
一、背景:为什么需要巡检脚本?
在金融、政务、企业级应用中,单位账户管理系统(Unit Account Management System)承担着核心账户数据管理职责,其稳定性直接关系到业务连续性。
我们采用 双机热备 + Keepalived + 虚拟IP(VIP) 的高可用架构,确保服务不中断。但在日常运维中,常遇到以下问题:
- ❓ 服务进程是否正常运行?
- ❓ 网络连通性是否正常?
- ❓ 虚拟IP当前落在哪台服务器?
- ❓ 磁盘/内存是否即将耗尽?
- ❓ 故障发生时,如何快速定位?
🔍 传统方式:登录服务器 → 逐条命令执行 → 手动记录 → 靠经验判断
💡 理想方式:一键巡检,自动生成报告,关键信息一目了然
于是,我们开发了这套 单位账户管理系统专用巡检脚本,实现 “5分钟快速排查”。
二、脚本功能概览
检查项 | 实现方式 |
---|---|
✅ 服务进程状态 | ps -ef 检查 afas_gateway 、af-as-start |
✅ 端口监听状态 | ss -tuln 检查 9088、8088、3306 |
✅ Docker 容器状态 | docker inspect 检查 aml_nginx |
✅ MySQL 服务状态 | systemctl is-active mysql |
✅ 网络连通性 | telnet 模拟连接(使用 /dev/tcp ) |
✅ Keepalived 与 VIP 状态 | ip addr show 判断是否持有 7.12.0.100 |
✅ 系统资源使用 | df -h 磁盘、free -m 内存 |
✅ 日志输出 | 屏幕 + 自动命名日志文件 |
🎯 核心亮点:
✅ 不依赖日志判断主备角色 → 通过 IP 存在性判断更准确
✅ 自动识别业务网段 IP → 避免误读 Docker/IPV6 地址
✅ 资源使用率超标自动标红 ⚠️ → 快速发现瓶颈
三、脚本核心逻辑解析
1. 如何判断虚拟IP(VIP)当前在哪台服务器?
传统做法是通过 journalctl -u keepalived
查看日志中的 MASTER
字样,但存在日志轮转、延迟、权限问题。
我们采用更直接的方式:
if ip addr show | grep -q "7.12.0.100"; thenecho "❤️ 虚拟IP由本机提供服务"
elseecho " standby,由其他节点提供服务"
fi
✅ 优势:只要 VIP 绑定成功,就能立即识别,100% 准确
2. 如何智能获取“业务IP”?
服务器可能有多个 IP(Loopback、Docker、IPv6、业务网段),我们通过过滤排除非业务网段:
local ip=$(hostname -I | awk '{for(i=1;i<=NF;i++) if($i !~ /^127\.|^172\.|^192\.168\./) print $i; exit
}')
👉 优先匹配非 127.x
、非 172.x
、非 192.168.x
的 IP,确保输出的是真实业务 IP(如 7.12.0.97
)
3. 资源检查:磁盘 & 内存
磁盘使用(df -h
)
- 仅显示
/dev/
开头的真实磁盘 - 根目录
/
单独检查 - 使用率 >80% 标出 ⚠️ 警告
内存使用(free -m
)
- 计算使用率百分比
-
80% 标出 ⚠️
[INFO] 内存使用情况 (free -m):使用: 7800 MB / 总计: 16000 MB → 使用率: 48%
4. 网络连通性检测(无 telnet 依赖)
使用 Bash 内置 /dev/tcp
实现超时连接检测,无需安装 telnet
:
timeout 3 bash -c "cat < /dev/null > /dev/tcp/7.12.0.100/9088"
支持检测:
- Start → Gateway
- Gateway → 国密Nginx
- 国密Nginx → Gateway
- Gateway → Start
四、完整脚本代码
#!/bin/bash#====================================================
# 单位账户管理系统状态巡检脚本(只读模式)
# 用途: 检查服务状态、网络、Keepalived、IP、磁盘、内存
# 输出: 屏幕 + 日志文件
#====================================================LOG_FILE="/home/cfit/logs/unit_account_check_$(date +%Y%m%d_%H%M%S).log"
START_TIME=$(date '+%Y-%m-%d %H:%M:%S')mkdir -p /home/cfit/logslog() {local msg="$*"local timestamp=$(date '+%H:%M:%S')echo "[$timestamp] $msg"echo "[$timestamp] $msg" >> "$LOG_FILE"
}# 检查进程
check_process() {if ps -ef | grep "$1" | grep -v "grep" > /dev/null 2>&1; thenlog "[OK] $2 进程正在运行"elselog "[MISSING] $2 进程未找到"fi
}# 检查端口
check_port() {if ss -tuln | grep -q ":$1 "; thenlog "[OK] 端口 $1 正在监听 ($2)"elselog "[CLOSED] 端口 $1 未监听 ($2)"fi
}# 检查 Docker
check_docker_container() {local status=$(docker inspect "$1" --format '{{.State.Status}}' 2>/dev/null)if [ $? -eq 0 ]; thenif [ "$status" = "running" ]; thenlog "[OK] $2 容器运行中"elselog "[STOPPED] $2 容器未运行"fielselog "[ERROR] 无法获取 $2 容器状态"fi
}# 检查 systemctl 服务
check_systemctl() {if systemctl is-active "$1" > /dev/null 2>&1; thenlog "[OK] $2 服务正在运行"elif systemctl is-enabled "$1" > /dev/null 2>&1; thenlog "[STOPPED] $2 服务已安装但未运行"elselog "[MISSING] $2 服务未启用或不存在"fi
}# 检查网络连通性
check_telnet() {log "[INFO] 检测: $3 ..."if timeout 3 bash -c "cat < /dev/null > /dev/tcp/$1/$2" 2>/dev/null; thenlog "[OK] $3 连接成功"elselog "[FAILED] $3 连接失败"fi
}# 检查 Keepalived 与 VIP
check_keepalived() {log "[INFO] ------------------------------"log "[INFO] 检查 Keepalived 与虚拟IP状态..."check_systemctl "keepalived" "Keepalived"local ip=$(hostname -I | awk '{for(i=1;i<=NF;i++) if($i !~ /^127\.|^172\.|^192\.168\./) print $i; exit}' || \ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1 | head -1)log "[INFO] 当前服务器物理 IP: $ip"local vip="7.12.0.100"if ip addr show | grep -q "$vip"; thenlog "[ACTIVE] ❤️ 虚拟IP $vip 当前由本机($ip)提供服务"elselog "[STANDBY] 虚拟IP $vip 当前由其他服务器提供服务(本机未持有)"fi
}# 检查资源
check_system_resources() {log "[INFO] ------------------------------"log "[INFO] 检查系统资源使用情况..."log "[INFO] 磁盘使用情况 (df -h):"df -h | grep -E '^/dev/' | while read line; dolocal use=$(echo "$line" | awk '{print $5}' | tr -d '%')if [ "$use" -gt 80 ]; thenlog " ⚠️ $(echo "$line" | awk '{printf "[%s] %s used=%s, %s → 使用率: %s", $1, $2, $3, $6, $5}') (偏高!)"elselog " $(echo "$line" | awk '{printf "[%s] %s used=%s, %s → 使用率: %s", $1, $2, $3, $6, $5}')"fidonedf -h / | tail -1 | while read line; dolocal use=$(echo "$line" | awk '{print $5}' | tr -d '%')if [ "$use" -gt 80 ]; thenlog " ⚠️ [根目录 /] $(echo "$line" | awk '{print $2, "used=" $3}') → 使用率: ${use}% (偏高!)"elselog " [根目录 /] $(echo "$line" | awk '{print $2, "used=" $3}') → 使用率: ${use}%"fidonelog "[INFO] 内存使用情况 (free -m):"local total=$(free -m | grep "^Mem:" | awk '{print $2}')local used=$(free -m | grep "^Mem:" | awk '{print $3}')local percent=$((used * 100 / total))if [ "$percent" -gt 80 ]; thenlog " ⚠️ 使用: $used MB / 总计: $total MB → 使用率: ${percent}% (偏高!)"elselog " 使用: $used MB / 总计: $total MB → 使用率: ${percent}%"fi
}#============================================
# 开始巡检
#============================================log "[INFO] ==================== 单位账户管理系统状态巡检开始 ===================="
log "[INFO] 巡检时间: $START_TIME"# 检查服务
check_process "afas_gateway" "afas_gateway"
check_port 9088 "afas_gateway"
check_process "af-as-start" "af-as-start"
check_port 8088 "af-as-start"
check_docker_container "aml_nginx" "aml_nginx"
check_systemctl "mysql" "MySQL"
check_port 3306 "MySQL"# 网络检测
check_telnet "7.12.0.100" "9088" "Start → Gateway"
check_telnet "7.12.0.101" "9001" "Gateway → 国密Nginx"
check_telnet "7.12.0.100" "9088" "国密Nginx → Gateway"
check_telnet "7.12.0.100" "8088" "Gateway → Start"# Keepalived 与资源
check_keepalived
check_system_resources# 结束
END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
log "[INFO] ==================== 巡检完成 ===================="
log "[INFO] 开始时间: $START_TIME"
log "[INFO] 结束时间: $END_TIME"
log "[INFO] 日志已保存至: $LOG_FILE"
原文件
#!/bin/bash#====================================================
# 单位账户管理系统状态巡检脚本(只读模式)
# 用途: 检查服务状态、网络、Keepalived 角色、IP、磁盘、内存
# 输出: 屏幕 + 日志文件
#====================================================# 配置变量
LOG_FILE="/home/cfit/logs/afas_check_status_$(date +%Y%m%d_%H%M%S).log"
START_TIME=$(date '+%Y-%m-%d %H:%M:%S')# 创建日志目录
mkdir -p /home/cfit/logs# 日志函数(同时输出到屏幕和文件)
log() {local msg="$*"local timestamp=$(date '+%H:%M:%S')echo "[$timestamp] $msg"echo "[$timestamp] $msg" >> "$LOG_FILE"
}# 检查进程是否运行(使用 ps -ef | grep,排除 grep 自身)
check_process() {local pattern=$1local desc=$2if ps -ef | grep "$pattern" | grep -v "grep" > /dev/null 2>&1; thenlog "[OK] $desc 进程正在运行"elselog "[MISSING] $desc 进程未找到"fi
}# 检查端口是否监听
check_port() {local port=$1local desc=$2if ss -tuln | grep -q ":$port "; thenlog "[OK] 端口 $port 正在监听 ($desc)"elselog "[CLOSED] 端口 $port 未监听 ($desc)"fi
}# 检查 Docker 容器状态
check_docker_container() {local container_name=$1local desc=$2local status=$(docker inspect "$container_name" --format '{{.State.Status}}' 2>/dev/null)if [ $? -eq 0 ]; thenif [ "$status" = "running" ]; thenlog "[OK] $desc 容器运行中 (状态: $status)"elselog "[STOPPED] $desc 容器未运行 (状态: $status)"fielselog "[ERROR] 无法获取 $desc 容器状态(可能不存在或 Docker 未启动)"fi
}# 检查 systemctl 服务状态
check_systemctl() {local service_name=$1local desc=$2if systemctl is-active "$service_name" > /dev/null 2>&1; thenlog "[OK] $desc 服务正在运行"elif systemctl is-enabled "$service_name" > /dev/null 2>&1; thenlog "[STOPPED] $desc 服务已安装但未运行"elselog "[MISSING] $desc 服务未启用或不存在"fi
}# 检测 telnet 连通性
check_telnet() {local ip=$1local port=$2local desc=$3log "[INFO] 检测: $desc (telnet $ip $port) ..."if timeout 3 bash -c "cat < /dev/null > /dev/tcp/$ip/$port" 2>/dev/null; thenlog "[OK] $desc 连接成功"elselog "[FAILED] $desc 连接失败"fi
}#============================================
# 新增:检查 Keepalived 相关信息(基于虚拟IP存在性)
#============================================check_keepalived() {log "[INFO] ------------------------------"log "[INFO] 检查 Keepalived 与虚拟IP状态..."# 1. 检查 keepalived 服务是否运行check_systemctl "keepalived" "Keepalived"# 2. 获取当前服务器主要物理 IPlocal ip=$(hostname -I | awk '{for(i=1;i<=NF;i++) if($i !~ /^127\.|^172\.|^192\.168\./) print $i; exit}' || \ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1 | head -1)log "[INFO] 当前服务器物理 IP: $ip"# 3. 检查是否绑定了虚拟 IP(7.12.0.100)local vip="7.12.0.100"if ip addr show | grep -q "$vip"; thenlog "[ACTIVE] ❤️ 虚拟IP $vip 当前由本机($ip)提供服务"elselog "[STANDBY] 虚拟IP $vip 当前由其他服务器提供服务(本机未持有)"fi
}#============================================
# 新增:检查系统资源(磁盘、内存)
#============================================check_system_resources() {log "[INFO] ------------------------------"log "[INFO] 检查系统资源使用情况..."# 1. 磁盘使用情况(df -h,过滤掉 tmpfs、run 等)log "[INFO] 磁盘使用情况 (df -h):"df -h | grep -E '^/dev/' | while read line; dolocal use_percent=$(echo "$line" | awk '{print $5}' | tr -d '%')local filesystem=$(echo "$line" | awk '{print $1}')local size=$(echo "$line" | awk '{print $2}')local used=$(echo "$line" | awk '{print $3}')local mount=$(echo "$line" | awk '{print $6}')if [ "$use_percent" -gt 80 ]; thenlog " ⚠️ [$filesystem] $size used=$used, $mount → 使用率: ${use_percent}% (偏高!)"elselog " [$filesystem] $size used=$used, $mount → 使用率: ${use_percent}%"fidone# 补充:检查根目录 / 是否高使用率(有时不在 /dev/ 下)df -h / | tail -1 | while read line; dolocal use_percent=$(echo "$line" | awk '{print $5}' | tr -d '%')local size=$(echo "$line" | awk '{print $2}')local used=$(echo "$line" | awk '{print $3}')if [ "$use_percent" -gt 80 ]; thenlog " ⚠️ [根目录 /] $size used=$used → 使用率: ${use_percent}% (偏高!)"elselog " [根目录 /] $size used=$used → 使用率: ${use_percent}%"fidone# 2. 内存使用情况(free -m)log "[INFO] 内存使用情况 (free -m):"local mem_total=$(free -m | grep "^Mem:" | awk '{print $2}')local mem_used=$(free -m | grep "^Mem:" | awk '{print $3}')local mem_free=$(free -m | grep "^Mem:" | awk '{print $4}')local mem_percent=$(( mem_used * 100 / mem_total ))if [ "$mem_percent" -gt 80 ]; thenlog " ⚠️ 使用: $mem_used MB / 总计: $mem_total MB → 使用率: ${mem_percent}% (偏高!)"elselog " 使用: $mem_used MB / 总计: $mem_total MB → 使用率: ${mem_percent}%"fi
}#============================================
# 开始巡检
#============================================log "[INFO] ==================== 单位账户管理系统状态巡检开始 ===================="
log "[INFO] 巡检时间: $START_TIME"# 1. 检查 afas_gateway 服务
log "[INFO] ------------------------------"
log "[INFO] 检查 afas_gateway 服务状态..."
check_process "afas_gateway" "afas_gateway"
check_port 9088 "afas_gateway 服务端口"# 2. 检查 af-as-start 服务
log "[INFO] ------------------------------"
log "[INFO] 检查 af-as-start 服务状态..."
check_process "af-as-start" "af-as-start"
check_port 8088 "af-as-start 服务端口"# 3. 检查 aml_nginx (Docker)
log "[INFO] ------------------------------"
log "[INFO] 检查 aml_nginx 容器状态..."
check_docker_container "aml_nginx" "aml_nginx"# 4. 检查 MySQL
log "[INFO] ------------------------------"
log "[INFO] 检查 MySQL 服务状态..."
check_systemctl "mysql" "MySQL"
check_port 3306 "MySQL 数据库端口"#============================================
# 网络连通性检测
#============================================log "[INFO] ==================== 网络连通性检测 ===================="check_telnet "7.12.0.100" "9088" "Start → Gateway"
check_telnet "7.12.0.101" "9001" "Gateway → 国密Nginx"
check_telnet "7.12.0.100" "9088" "国密Nginx → Gateway"
check_telnet "7.12.0.100" "8088" "Gateway → Start"#============================================
# 新增:Keepalived 状态检查
#============================================check_keepalived#============================================
# 新增:系统资源检查(磁盘、内存)
#============================================check_system_resources#============================================
# 巡检完成
#============================================END_TIME=$(date '+%Y-%m-%d %H:%M:%S')
log "[INFO] ==================== 巡检完成 ===================="
log "[INFO] 开始时间: $START_TIME"
log "[INFO] 结束时间: $END_TIME"
log "[INFO] 日志已保存至: $LOG_FILE"
执行的结果
[root@cfit2 tmp]# sh check_unit_account_system_status.sh
[17:01:39] [INFO] ==================== 单位账户管理系统状态巡检开始 ====================
[17:01:39] [INFO] 巡检时间: 2025-10-16 17:01:39
[17:01:39] [INFO] ------------------------------
[17:01:39] [INFO] 检查 afas_gateway 服务状态...
[17:01:39] [OK] afas_gateway 进程正在运行
[17:01:39] [OK] 端口 9088 正在监听 (afas_gateway 服务端口)
[17:01:39] [INFO] ------------------------------
[17:01:39] [INFO] 检查 af-as-start 服务状态...
[17:01:39] [OK] af-as-start 进程正在运行
[17:01:39] [OK] 端口 8088 正在监听 (af-as-start 服务端口)
[17:01:39] [INFO] ------------------------------
[17:01:39] [INFO] 检查 aml_nginx 容器状态...
[17:01:39] [OK] aml_nginx 容器运行中 (状态: running)
[17:01:39] [INFO] ------------------------------
[17:01:39] [INFO] 检查 MySQL 服务状态...
[17:01:39] [OK] MySQL 服务正在运行
[17:01:39] [OK] 端口 3306 正在监听 (MySQL 数据库端口)
[17:01:39] [INFO] ==================== 网络连通性检测 ====================
[17:01:39] [INFO] 检测: Start → Gateway (telnet 7.12.0.100 9088) ...
[17:01:39] [OK] Start → Gateway 连接成功
[17:01:39] [INFO] 检测: Gateway → 国密Nginx (telnet 7.12.0.101 9001) ...
[17:01:39] [OK] Gateway → 国密Nginx 连接成功
[17:01:39] [INFO] 检测: 国密Nginx → Gateway (telnet 7.12.0.100 9088) ...
[17:01:39] [OK] 国密Nginx → Gateway 连接成功
[17:01:39] [INFO] 检测: Gateway → Start (telnet 7.12.0.100 8088) ...
[17:01:39] [OK] Gateway → Start 连接成功
[17:01:39] [INFO] ------------------------------
[17:01:39] [INFO] 检查 Keepalived 与虚拟IP状态...
[17:01:39] [OK] Keepalived 服务正在运行
[17:01:39] [INFO] 当前服务器物理 IP: 7.12.0.97
7.12.0.100
[17:01:39] [ACTIVE] ❤️ 虚拟IP 7.12.0.100 当前由本机(7.12.0.97
7.12.0.100)提供服务
[17:01:39] [INFO] ------------------------------
[17:01:39] [INFO] 检查系统资源使用情况...
[17:01:39] [INFO] 磁盘使用情况 (df -h):
[17:01:39] [/dev/mapper/rootvg-root] 50G used=7.7G, / → 使用率: 16%
[17:01:39] [/dev/mapper/datavg-lv_u01] 50G used=33M, /u01 → 使用率: 1%
[17:01:39] [/dev/mapper/datavg-lv_mysqldata] 300G used=6.3G, /mysqldata → 使用率: 3%
[17:01:39] [/dev/mapper/datavg-lv_home] 100G used=54G, /home → 使用率: 54%
[17:01:39] [/dev/vda1] 497M used=143M, /boot → 使用率: 29%
[17:01:39] [根目录 /] 50G used=7.7G → 使用率: 16%
[17:01:39] [INFO] 内存使用情况 (free -m):
[17:01:39] 使用: 5291 MB / 总计: 32010 MB → 使用率: 16%
[17:01:39] [INFO] ==================== 巡检完成 ====================
[17:01:39] [INFO] 开始时间: 2025-10-16 17:01:39
[17:01:39] [INFO] 结束时间: 2025-10-16 17:01:39
[17:01:39] [INFO] 日志已保存至: /home/cfit/logs/afas_check_status_20251016_170139.log
[root@cfit2 tmp]#
五、使用方法
1. 保存脚本
vim /opt/inspection/check_unit_account_system_status.sh
2. 赋予权限
chmod +x /opt/inspection/check_unit_account_system_status.sh
3. 执行巡检
/opt/inspection/check_unit_account_system_status.sh
4. 查看日志
tail -f /home/cfit/logs/unit_account_check_*.log
六、后续优化方向
- 📊 生成 HTML 报告,支持浏览器查看
- 📱 集成企业微信/钉钉通知,异常自动告警
- 🕰️ 加入
crontab
定时每日凌晨巡检 - 📈 数据采集 + Grafana 可视化
七、总结
通过这个巡检脚本,我们实现了:
✅ 一键排查:5分钟内完成全系统状态检查
✅ 精准判断:基于 IP 绑定判断主备,比日志更可靠
✅ 自动记录:每次巡检生成独立日志,便于追溯
✅ 易于扩展:模块化设计,可适配其他系统
🌟 运维的本质,是把重复的工作自动化,把复杂的问题可视化。
这套脚本已在生产环境稳定运行数月,极大提升了我们的故障响应效率。希望对你也有帮助!
欢迎点赞、收藏、转发!
如有疑问或建议,欢迎在评论区交流 👇
#运维 #Shell脚本 #Keepalived #高可用 #巡检脚本 #Linux #自动化 #单位账户管理系统
版权声明:本文原创,转载请注明出处。