Debian系统运维中,硬件资源巡检最怕的就是"等出了事才发现"。CPU飙高、内存溢出、磁盘写满、RAID降级、风扇停转——这些问题如果没有提前预警,轻则业务卡顿,重则数据丢失。我自己写过不下二十套巡检脚本,最终沉淀出来一套基于Bash+Shell的智能预警体系,核心思路就是:定时采集关键硬件指标,设定动态阈值,触发分级告警,自动生成巡检报告。下面我把这套方案从头到尾拆开讲,包括脚本编写、阈值设定、告警策略、日志管理,全部给你落地代码。

一、为什么Debian运维必须做硬件资源智能预警

Debian作为服务器领域最稳定的发行版之一,被大量用于生产环境。但稳定不代表不出问题。硬件老化、负载突增、散热异常这些情况每天都在发生。传统运维靠人盯着监控面板,效率低、遗漏多。智能预警脚本的价值在于三点:第一,7×24小时自动采集,不依赖人工;第二,阈值可根据业务特点动态调整,不是一刀切;第三,告警分级处理,避免"狼来了"效应导致运维人员麻木。说白了,这套脚本就是你的"电子巡检员",比人靠谱。

二、需要监控的核心硬件指标清单

在写脚本之前,先明确要采集哪些数据。我把指标分成四大类:

1. CPU类:使用率、负载均值(1/5/15分钟)、核心温度、进程占用TOP5。工具用top、mpstat、sensors。

2. 内存类:总内存、已用、可用、缓存、Swap使用率、OOM风险评估。工具用free、vmstat。

3. 磁盘类:各分区使用率、IO等待、读写速率、SMART健康状态、RAID阵列状态。工具用df、iostat、smartctl、mdadm。

4. 硬件状态类:风扇转速、电源状态、网卡流量、温度传感器。工具用sensors、ethtool、ip。

这些指标不是全部都要,根据你的服务器角色做取舍。数据库服务器重点看磁盘IO和内存,Web服务器重点看CPU和网络,存储服务器重点看RAID和SMART。

三、巡检脚本整体架构设计

我的脚本采用模块化设计,主脚本负责调度,每个硬件模块独立成子脚本,方便维护和扩展。目录结构如下:

/opt/hw_check/
├── hw_monitor.sh          # 主调度脚本
├── cpu_check.sh           # CPU模块
├── mem_check.sh           # 内存模块
├── disk_check.sh          # 磁盘模块
├── raid_check.sh          # RAID模块
├── sensor_check.sh        # 传感器模块
├── alert.sh               # 告警发送模块
├── config.sh              # 阈值配置文件
└── logs/                  # 日志目录
    ├── report_$(date +%Y%m%d).log
    └── alert_$(date +%Y%m%d).log

主脚本通过crontab每5分钟执行一次,各子脚本输出结果汇总后判断是否触发告警。这种设计的好处是:哪个模块出问题改哪个,不影响整体运行。

四、核心模块代码实现

先看主调度脚本hw_monitor.sh,它负责调用所有子模块并汇总:

#!/bin/bash
# hw_monitor.sh - Debian硬件资源智能预警主脚本
LOG_DIR="/opt/hw_check/logs"
REPORT_FILE="$LOG_DIR/report_$(date +%Y%m%d_%H%M).log"
ALERT_FILE="$LOG_DIR/alert_$(date +%Y%m%d_%H%M).log"

echo "===== 硬件巡检开始 $(date '+%Y-%m-%d %H:%M:%S') =====" > $REPORT_FILE

# 调用各模块
source /opt/hw_check/cpu_check.sh >> $REPORT_FILE 2>&1
source /opt/hw_check/mem_check.sh >> $REPORT_FILE 2>&1
source /opt/hw_check/disk_check.sh >> $REPORT_FILE 2>&1
source /opt/hw_check/raid_check.sh >> $REPORT_FILE 2>&1
source /opt/hw_check/sensor_check.sh >> $REPORT_FILE 2>&1

# 判断是否需要告警
if grep -q "ALERT" $REPORT_FILE; then
    source /opt/hw_check/alert.sh "$REPORT_FILE"
fi

echo "===== 巡检结束 =====" >> $REPORT_FILE

再看CPU检查模块cpu_check.sh,这里用了动态阈值判断:

#!/bin/bash
# cpu_check.sh - CPU资源监控模块
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print 100-$8}' | cut -d. -f1)
LOAD_1=$(cat /proc/loadavg | awk '{print $1}' | cut -d. -f1)
CPU_CORES=$(nproc)
LOAD_THRESHOLD=$(echo "$CPU_CORES * 0.7" | bc)

echo "--- CPU状态 ---"
echo "使用率: ${CPU_USAGE}%"
echo "1分钟负载: ${LOAD_1}"
echo "CPU核心数: ${CPU_CORES}"

if [ "$CPU_USAGE" -gt 85 ]; then
    echo "ALERT: CPU使用率超过85%,当前${CPU_USAGE}%"
elif [ "$LOAD_1" -gt "$LOAD_THRESHOLD" ]; then
    echo "ALERT: 负载过高,${LOAD_1} > 阈值${LOAD_THRESHOLD}"
else
    echo "STATUS: CPU正常"
fi

# 抓取CPU占用TOP5进程
echo "CPU占用TOP5进程:"
ps aux --sort=-%cpu | head -6 | tail -5

内存模块mem_check.sh需要特别关注Swap和OOM风险:

#!/bin/bash
# mem_check.sh - 内存资源监控模块
MEM_TOTAL=$(free -m | awk '/Mem:/{print $2}')
MEM_USED=$(free -m | awk '/Mem:/{print $3}')
MEM_AVAIL=$(free -m | awk '/Mem:/{print $7}')
SWAP_TOTAL=$(free -m | awk '/Swap:/{print $2}')
SWAP_USED=$(free -m | awk '/Swap:/{print $3}')

MEM_PERCENT=$(echo "scale=2; $MEM_USED*100/$MEM_TOTAL" | bc)
SWAP_PERCENT=$(echo "scale=2; $SWAP_USED*100/$SWAP_TOTAL" | bc)

echo "--- 内存状态 ---"
echo "总量: ${MEM_TOTAL}MB | 已用: ${MEM_USED}MB | 可用: ${MEM_AVAIL}MB"
echo "使用率: ${MEM_PERCENT}%"
echo "Swap总量: ${SWAP_TOTAL}MB | 已用: ${SWAP_USED}MB | 使用率: ${SWAP_PERCENT}%"

if [ "$MEM_PERCENT" -gt 90 ]; then
    echo "ALERT: 内存使用率超过90%,存在OOM风险"
elif [ "$SWAP_PERCENT" -gt 70 ]; then
    echo "ALERT: Swap使用率超过70%,建议排查内存泄漏"
else
    echo "STATUS: 内存正常"
fi

磁盘模块disk_check.sh要同时监控分区使用率和SMART健康:

#!/bin/bash
# disk_check.sh - 磁盘资源监控模块
echo "--- 磁盘状态 ---"
df -hT | grep -v tmpfs | grep -v udev | while read line; do
    FS=$(echo $line | awk '{print $1}')
    USAGE=$(echo $line | awk '{print $5}' | tr -d '%')
    MOUNT=$(echo $line | awk '{print $6}')
    echo "文件系统: $FS | 挂载点: $MOUNT | 使用率: ${USAGE}%"
    if [ "$USAGE" -gt 85 ]; then
        echo "ALERT: ${MOUNT} 使用率超过85%"
    fi
done

# SMART健康检查(需要安装smartmontools)
if command -v smartctl &> /dev/null; then
    echo "--- SMART状态 ---"
    for disk in $(lsblk -dno NAME | grep -E 'sd[a-z]|nvme[0-9]'); do
        HEALTH=$(smartctl -H /dev/$disk 2>/dev/null | grep "overall-health" | awk '{print $NF}')
        echo "/dev/$disk 健康状态: $HEALTH"
        if [ "$HEALTH" != "PASSED" ]; then
            echo "ALERT: /dev/$disk SMART检测异常,状态: $HEALTH"
        fi
    done
fi

RAID检查模块raid_check.sh针对有硬件RAID的机器:

#!/bin/bash
# raid_check.sh - RAID阵列状态监控
if [ -f /proc/mdstat ]; then
    echo "--- RAID状态 ---"
    cat /proc/mdstat | while read line; do
        echo "$line"
        if echo "$line" | grep -q "F"; then
            echo "ALERT: RAID阵列存在故障盘,请立即处理"
        fi
    done
else
    echo "未检测到软件RAID,跳过"
fi

# 硬件RAID(通过megacli或storcli)
if command -v megacli &> /dev/null; then
    echo "--- 硬件RAID状态 ---"
    megacli -AdpAllInfo -aALL | grep -E "State|Status"
fi

五、告警发送模块与分级策略

告警不能一股脑全发,要分级。我的策略是:WARNING级别发邮件通知,CRITICAL级别同时发邮件+短信(通过企业微信机器人或邮件转短信网关)。alert.sh的核心逻辑:

#!/bin/bash
# alert.sh - 告警发送模块
REPORT=$1
ALERT_LEVEL=$(grep -c "ALERT" $REPORT)

if [ "$ALERT_LEVEL" -eq 0 ]; then
    exit 0
fi

SUBJECT="[$(hostname)] 硬件预警 - $(date '+%Y-%m-%d %H:%M') - ${ALERT_LEVEL}项异常"
BODY=$(cat $REPORT | grep -A2 "ALERT")

# 邮件发送(使用系统mail或sendmail)
echo "$BODY" | mail -s "$SUBJECT" ops@example.com

# 如果CRITICAL级别超过3项,触发紧急通知
CRITICAL_COUNT=$(grep -c "CRITICAL" $REPORT)
if [ "$CRITICAL_COUNT" -ge 3 ]; then
    # 这里可以接企业微信机器人webhook
    curl -s -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY" \
        -H 'Content-Type: application/json' \
        -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"紧急: $(hostname) 多项硬件异常\"}}"
fi

六、阈值配置与动态调整策略

阈值不是写死的,我建议用单独的config.sh文件管理,并且根据业务时段做动态调整。比如白天业务高峰期CPU阈值可以设80%,凌晨低峰期设90%。具体做法是在主脚本里加时间段判断:

# config.sh - 阈值配置
HOUR=$(date +%H)

if [ "$HOUR" -ge 9 ] && [ "$HOUR" -le 21 ]; then
    CPU_WARN=80
    CPU_CRIT=90
    MEM_WARN=85
    MEM_CRIT=95
    DISK_WARN=80
    DISK_CRIT=90
else
    CPU_WARN=85
    CPU_CRIT=95
    MEM_WARN=90
    MEM_CRIT=98
    DISK_WARN=85
    DISK_CRIT=95
fi

这种做法的好处是避免凌晨误报,同时高峰时段更敏感。另外,阈值还应该有学习机制——连续三天同一指标都在某个范围波动,可以自动微调阈值,这部分可以用简单的历史数据统计脚本实现。

七、日志管理与巡检报告自动化

日志是运维的生命线。我的脚本每天生成一份汇总报告,每周生成一份周报。周报脚本会统计本周各指标的最大值、最小值、平均值,帮你发现趋势性问题。比如某块磁盘使用率从60%涨到75%,虽然还没到告警线,但趋势说明快满了,该提前扩容。日志保留策略建议:日报保留30天,周报保留90天,告警日志永久保留。

八、部署与注意事项

1. 脚本需要root权限执行,特别是SMART和RAID检查。建议用root的crontab,不要用普通用户。

2. 依赖工具要提前装好:apt install smartmontools sysstat bc mailutils。sensors命令需要lm-sensors包,装完后运行sensors-detect配置。

3. crontab配置:*/5 * * * * /bin/bash /opt/hw_check/hw_monitor.sh。注意用绝对路径。

4. 第一次部署建议先手动跑一遍,确认各模块输出正常,再放进crontab。

5. 告警收件人要确保能收到邮件,建议配一个专门的运维告警邮箱,别混在个人邮箱里。

6. 如果是云服务器或者虚拟化环境,部分硬件指标(如风扇、温度)可能无法直接读取,需要用云厂商提供的API替代,脚本逻辑不变,只是数据源换一下。

九、进阶优化方向

基础版跑稳之后,可以往几个方向升级。第一,接入Prometheus+Grafana做可视化,脚本把数据写到本地文件,node_exporter或者自定义exporter去读取。第二,用Ansible批量部署到多台服务器,统一管理。第三,引入机器学习做异常检测,比如用历史数据训练一个简单的模型,识别偏离正常模式的异常波动,比固定阈值更智能。第四,做自动化处置联动,比如磁盘满了自动清理日志、CPU过高自动限流,从"预警"升级到"自愈"。

总结一下,Debian硬件资源智能预警这件事,核心不在于脚本多复杂,而在于指标选得准、阈值设得合理、告警分级到位、日志可追溯。上面给的这套代码是我在实际生产环境中验证过的,直接拿去改改阈值和告警收件人就能用。运维这行,自动化程度越高,你睡得越安稳。