高可用巡检脚本实战:一键掌握服务、网络、VIP、资源状态

🛠️ 单位账户管理系统高可用巡检脚本实战:一键掌握服务、网络、VIP、资源状态

作者 :运维小记
场景 :单位账户管理系统(UAMS)
目标:构建一套全自动、可视化、高可用的服务器状态巡检方案


一、背景:为什么需要巡检脚本?

在金融、政务、企业级应用中,单位账户管理系统(Unit Account Management System)承担着核心账户数据管理职责,其稳定性直接关系到业务连续性。

我们采用 双机热备 + Keepalived + 虚拟IP(VIP) 的高可用架构,确保服务不中断。但在日常运维中,常遇到以下问题:

  • ❓ 服务进程是否正常运行?
  • ❓ 网络连通性是否正常?
  • ❓ 虚拟IP当前落在哪台服务器?
  • ❓ 磁盘/内存是否即将耗尽?
  • ❓ 故障发生时,如何快速定位?

🔍 传统方式:登录服务器 → 逐条命令执行 → 手动记录 → 靠经验判断

💡 理想方式:一键巡检,自动生成报告,关键信息一目了然

于是,我们开发了这套 单位账户管理系统专用巡检脚本 ,实现 "5分钟快速排查"


二、脚本功能概览

检查项 实现方式
✅ 服务进程状态 ps -ef 检查 afas_gatewayaf-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 #自动化 #单位账户管理系统


版权声明:本文原创,转载请注明出处。

相关推荐
时空潮汐4 小时前
无需公网 IP:神卓 K900 实现海康摄像头异地观看的两种简单方法
服务器·网络·tcp/ip·海康摄像头·神卓n600·神卓云监控
zx_zx_1234 小时前
传输层协议 tcp
服务器·网络·tcp/ip
鹿鸣天涯4 小时前
Wine 10.15 发布!Linux 跑 Windows 应用更丝滑了
linux·运维·windows
Allen Roson4 小时前
Burp Suite抓包软件使用说明1-Http history
网络·网络协议·http
爱吃芒果的蘑菇5 小时前
C++之WebSocket初体验
网络·c++·websocket·网络协议
Lynnxiaowen5 小时前
今天我们继续学习python3编程之python基础
linux·运维·python·学习
Do_GH5 小时前
【Docker】06.通过WSL部署Docker Desktop
运维·docker·容器
siriuuus5 小时前
Nginx IP 透传
网络·nginx
40kuai5 小时前
nginx server_tokens 和proxy_hide_header的差别
运维·nginx