🛠️ 单位账户管理系统高可用巡检脚本实战:一键掌握服务、网络、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
字样,但存在日志轮转、延迟、权限问题。
我们采用更直接的方式:
bash
if ip addr show | grep -q "7.12.0.100"; then
echo "❤️ 虚拟IP由本机提供服务"
else
echo " standby,由其他节点提供服务"
fi
✅ 优势 :只要 VIP 绑定成功,就能立即识别,100% 准确
2. 如何智能获取"业务IP"?
服务器可能有多个 IP(Loopback、Docker、IPv6、业务网段),我们通过过滤排除非业务网段:
bash
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% 标出 ⚠️
bash
[INFO] 内存使用情况 (free -m):
使用: 7800 MB / 总计: 16000 MB → 使用率: 48%
4. 网络连通性检测(无 telnet 依赖)
使用 Bash 内置 /dev/tcp
实现超时连接检测,无需安装 telnet
:
bash
timeout 3 bash -c "cat < /dev/null > /dev/tcp/7.12.0.100/9088"
支持检测:
- Start → Gateway
- Gateway → 国密Nginx
- 国密Nginx → Gateway
- Gateway → Start
四、完整脚本代码
bash
#!/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/logs
log() {
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; then
log "[OK] $2 进程正在运行"
else
log "[MISSING] $2 进程未找到"
fi
}
# 检查端口
check_port() {
if ss -tuln | grep -q ":$1 "; then
log "[OK] 端口 $1 正在监听 ($2)"
else
log "[CLOSED] 端口 $1 未监听 ($2)"
fi
}
# 检查 Docker
check_docker_container() {
local status=$(docker inspect "$1" --format '{{.State.Status}}' 2>/dev/null)
if [ $? -eq 0 ]; then
if [ "$status" = "running" ]; then
log "[OK] $2 容器运行中"
else
log "[STOPPED] $2 容器未运行"
fi
else
log "[ERROR] 无法获取 $2 容器状态"
fi
}
# 检查 systemctl 服务
check_systemctl() {
if systemctl is-active "$1" > /dev/null 2>&1; then
log "[OK] $2 服务正在运行"
elif systemctl is-enabled "$1" > /dev/null 2>&1; then
log "[STOPPED] $2 服务已安装但未运行"
else
log "[MISSING] $2 服务未启用或不存在"
fi
}
# 检查网络连通性
check_telnet() {
log "[INFO] 检测: $3 ..."
if timeout 3 bash -c "cat < /dev/null > /dev/tcp/$1/$2" 2>/dev/null; then
log "[OK] $3 连接成功"
else
log "[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"; then
log "[ACTIVE] ❤️ 虚拟IP $vip 当前由本机($ip)提供服务"
else
log "[STANDBY] 虚拟IP $vip 当前由其他服务器提供服务(本机未持有)"
fi
}
# 检查资源
check_system_resources() {
log "[INFO] ------------------------------"
log "[INFO] 检查系统资源使用情况..."
log "[INFO] 磁盘使用情况 (df -h):"
df -h | grep -E '^/dev/' | while read line; do
local use=$(echo "$line" | awk '{print $5}' | tr -d '%')
if [ "$use" -gt 80 ]; then
log " ⚠️ $(echo "$line" | awk '{printf "[%s] %s used=%s, %s → 使用率: %s", $1, $2, $3, $6, $5}') (偏高!)"
else
log " $(echo "$line" | awk '{printf "[%s] %s used=%s, %s → 使用率: %s", $1, $2, $3, $6, $5}')"
fi
done
df -h / | tail -1 | while read line; do
local use=$(echo "$line" | awk '{print $5}' | tr -d '%')
if [ "$use" -gt 80 ]; then
log " ⚠️ [根目录 /] $(echo "$line" | awk '{print $2, "used=" $3}') → 使用率: ${use}% (偏高!)"
else
log " [根目录 /] $(echo "$line" | awk '{print $2, "used=" $3}') → 使用率: ${use}%"
fi
done
log "[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 ]; then
log " ⚠️ 使用: $used MB / 总计: $total MB → 使用率: ${percent}% (偏高!)"
else
log " 使用: $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"
原文件
bash
#!/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=$1
local desc=$2
if ps -ef | grep "$pattern" | grep -v "grep" > /dev/null 2>&1; then
log "[OK] $desc 进程正在运行"
else
log "[MISSING] $desc 进程未找到"
fi
}
# 检查端口是否监听
check_port() {
local port=$1
local desc=$2
if ss -tuln | grep -q ":$port "; then
log "[OK] 端口 $port 正在监听 ($desc)"
else
log "[CLOSED] 端口 $port 未监听 ($desc)"
fi
}
# 检查 Docker 容器状态
check_docker_container() {
local container_name=$1
local desc=$2
local status=$(docker inspect "$container_name" --format '{{.State.Status}}' 2>/dev/null)
if [ $? -eq 0 ]; then
if [ "$status" = "running" ]; then
log "[OK] $desc 容器运行中 (状态: $status)"
else
log "[STOPPED] $desc 容器未运行 (状态: $status)"
fi
else
log "[ERROR] 无法获取 $desc 容器状态(可能不存在或 Docker 未启动)"
fi
}
# 检查 systemctl 服务状态
check_systemctl() {
local service_name=$1
local desc=$2
if systemctl is-active "$service_name" > /dev/null 2>&1; then
log "[OK] $desc 服务正在运行"
elif systemctl is-enabled "$service_name" > /dev/null 2>&1; then
log "[STOPPED] $desc 服务已安装但未运行"
else
log "[MISSING] $desc 服务未启用或不存在"
fi
}
# 检测 telnet 连通性
check_telnet() {
local ip=$1
local port=$2
local desc=$3
log "[INFO] 检测: $desc (telnet $ip $port) ..."
if timeout 3 bash -c "cat < /dev/null > /dev/tcp/$ip/$port" 2>/dev/null; then
log "[OK] $desc 连接成功"
else
log "[FAILED] $desc 连接失败"
fi
}
#============================================
# 新增:检查 Keepalived 相关信息(基于虚拟IP存在性)
#============================================
check_keepalived() {
log "[INFO] ------------------------------"
log "[INFO] 检查 Keepalived 与虚拟IP状态..."
# 1. 检查 keepalived 服务是否运行
check_systemctl "keepalived" "Keepalived"
# 2. 获取当前服务器主要物理 IP
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"
# 3. 检查是否绑定了虚拟 IP(7.12.0.100)
local vip="7.12.0.100"
if ip addr show | grep -q "$vip"; then
log "[ACTIVE] ❤️ 虚拟IP $vip 当前由本机($ip)提供服务"
else
log "[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; do
local 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 ]; then
log " ⚠️ [$filesystem] $size used=$used, $mount → 使用率: ${use_percent}% (偏高!)"
else
log " [$filesystem] $size used=$used, $mount → 使用率: ${use_percent}%"
fi
done
# 补充:检查根目录 / 是否高使用率(有时不在 /dev/ 下)
df -h / | tail -1 | while read line; do
local 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 ]; then
log " ⚠️ [根目录 /] $size used=$used → 使用率: ${use_percent}% (偏高!)"
else
log " [根目录 /] $size used=$used → 使用率: ${use_percent}%"
fi
done
# 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 ]; then
log " ⚠️ 使用: $mem_used MB / 总计: $mem_total MB → 使用率: ${mem_percent}% (偏高!)"
else
log " 使用: $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"
执行的结果
bash
[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. 保存脚本
bash
vim /opt/inspection/check_unit_account_system_status.sh
2. 赋予权限
bash
chmod +x /opt/inspection/check_unit_account_system_status.sh
3. 执行巡检
bash
/opt/inspection/check_unit_account_system_status.sh
4. 查看日志
bash
tail -f /home/cfit/logs/unit_account_check_*.log
六、后续优化方向
- 📊 生成 HTML 报告,支持浏览器查看
- 📱 集成企业微信/钉钉通知,异常自动告警
- 🕰️ 加入
crontab
定时每日凌晨巡检 - 📈 数据采集 + Grafana 可视化
七、总结
通过这个巡检脚本,我们实现了:
✅ 一键排查 :5分钟内完成全系统状态检查
✅ 精准判断 :基于 IP 绑定判断主备,比日志更可靠
✅ 自动记录 :每次巡检生成独立日志,便于追溯
✅ 易于扩展:模块化设计,可适配其他系统
🌟 运维的本质,是把重复的工作自动化,把复杂的问题可视化。
这套脚本已在生产环境稳定运行数月,极大提升了我们的故障响应效率。希望对你也有帮助!
欢迎点赞、收藏、转发!
如有疑问或建议,欢迎在评论区交流 👇
#运维 #Shell脚本 #Keepalived #高可用 #巡检脚本 #Linux #自动化 #单位账户管理系统
版权声明:本文原创,转载请注明出处。