shell实战练习脚本

柳三千

文章最后更新时间:2025年05月27日

系统资源监控脚本开发实战:精准告警与可视化输出

一、脚本概述

1. 核心功能

  • 多维度监控:实时监测CPU使用率、内存占用、磁盘利用率和系统负载
  • 智能告警:超过阈值时自动发送邮件通知管理员
  • 可视化输出:通过颜色标记状态(绿色-正常,黄色-警告,红色-严重)
  • 日志管理:自动轮转日志,避免文件无限增长

2. 技术特点

  • 精确计算:CPU使用率采用两次采样差值算法(基于/proc/stat
  • 浮点数支持:使用bc工具处理小数运算,确保精度
  • 健壮性设计:依赖检查、异常处理和模块化结构

二、环境配置与依赖

1. 系统要求

  • 操作系统:CentOS/Ubuntu等Linux发行版
  • 必备工具bc(用于数学计算)、mailx(邮件发送)、awk(文本处理)

2. 安装依赖(以CentOS为例)

yum install bc mailx -y

三、脚本代码解析

1. 颜色定义与状态标记

# 颜色定义(ANSI转义码)
GREEN='\033[0;32m'    # 正常
YELLOW='\033[1;33m'   # 警告
RED='\033[0;31m'      # 严重
BLUE='\033[0;34m'     # 信息
NC='\033[0m'          # 重置颜色

# 智能颜色标记函数(支持浮点数比较)
get_status_color() {
    local value="$1"
    local threshold="$2"
    
    if (( $(echo "$value > $threshold" | bc -l) )); then
        echo "$RED"  # 超过阈值显示红色
    elif (( $(echo "$value > ($threshold - 10)" | bc -l) )); then
        echo "$YELLOW"  # 接近阈值(阈值-10%)显示黄色
    else
        echo "$GREEN"  # 正常显示绿色
    fi
}

2. CPU监控(精确计算1分钟平均使用率)

monitor_cpu() {
    # 两次采样计算CPU差值(避免top命令的瞬时误差)
    local cpu1=($(awk '/cpu /{print $2+$3+$4+$5+$6+$7+$8,$5}' /proc/stat))
    sleep $INTERVAL_SEC
    local cpu2=($(awk '/cpu /{print $2+$3+$4+$5+$6+$7+$8,$5}' /proc/stat))
    
    local total_diff=$(( cpu2[0] - cpu1[0] ))
    local idle_diff=$(( cpu2[1] - cpu1[1] ))
    local usage=$(echo "scale=2; 100 - ($idle_diff * 100)/$total_diff" | bc)
    
    local color=$(get_status_color "$usage" "$CPU_THRESHOLD")
    log "CPU监控 | 使用率: ${color}${usage}%${NC} (阈值: ${CPU_THRESHOLD}%)"
    
    # 触发告警
    if (( $(echo "$usage >= $CPU_THRESHOLD" | bc -l) )); then
        echo "CPU使用率超过阈值: ${usage}%" | mail -s "CPU告警" "$ALERT_EMAIL"
    fi
}

3. 内存与磁盘监控

# 内存监控(基于free命令)
monitor_memory() {
    local mem_info=($(free -m | awk '/Mem/{print $2,$3}'))  # 总内存、已用内存(MB)
    local usage=$(echo "scale=2; ${mem_info[1]}*100/${mem_info[0]}" | bc)
    
    local color=$(get_status_color "$usage" "$MEM_THRESHOLD")
    log "内存监控 | 使用率: ${color}${usage}%${NC} (阈值: ${MEM_THRESHOLD}%)"
}

# 磁盘监控(根目录使用率)
monitor_disk() {
    local usage=$(df -h / | awk 'NR==2{sub(/%/, "", $5); print $5}')  # 提取数值(去掉%)
    local color=$(get_status_color "$usage" "$DISK_THRESHOLD")
    log "磁盘监控 | 使用率: ${color}${usage}%${NC} (阈值: ${DISK_THRESHOLD}%)"
}

4. 系统负载监控(基于核心数的负载系数)

monitor_load() {
    local cores=$(nproc)  # 获取CPU核心数
    local load1=$(uptime | awk -F 'load average: ' '{print $2}' | cut -d, -f1 | xargs)  # 1分钟负载
    local ratio=$(echo "scale=2; $load1 / $cores" | bc)  # 负载与核心数的比值
    
    local color=$(get_status_color "$ratio" "$LOAD_THRESHOLD")
    log "负载监控 | 当前值: ${color}${load1}${NC} (核心数: ${cores}, 阈值系数: ${LOAD_THRESHOLD})"
}

四、日志管理与轮转机制

# 日志轮转(限制日志大小为10MB,保留5个历史版本)
rotate_log() {
    [[ ! -f "$LOG_FILE" ]] && return
    
    local max_size_mb=10
    local current_size=$(du -m "$LOG_FILE" | awk '{print $1}')
    
    if (( current_size >= max_size_mb )); then
        echo -e "${BLUE}INFO: 日志轮转启动 (当前大小: ${current_size}MB)${NC}"
        for i in {5..1}; do
            [[ -f "${LOG_FILE}.$i" ]] && mv "${LOG_FILE}.$i" "${LOG_FILE}.$((i+1))"
        done
        mv "$LOG_FILE" "${LOG_FILE}.1"  # 重命名当前日志为1,新日志自动创建
    fi
}

# 统一日志记录函数
log() {
    rotate_log
    local timestamp=$(date "+%F %T")
    echo -e "[$timestamp] $1" | tee -a "$LOG_FILE"  # 同时输出到终端和日志文件
}

五、使用示例与输出效果

1. 正常状态(绿色)

=== 系统监控启动 [2025-05-27 15:00:00] ===
[2025-05-27 15:00:00] CPU监控 | 使用率: 25.34% (阈值: 85%)
[2025-05-27 15:00:00] 内存监控 | 使用率: 62.15% (阈值: 85%)
[2025-05-27 15:00:00] 磁盘监控 | 使用率: 35% (阈值: 85%)
[2025-05-27 15:00:00] 负载监控 | 当前值: 0.85 (核心数: 4, 阈值系数: 1.5)
=== 监控完成 [2025-05-27 15:00:01] ===

2. 告警状态(红色)

[2025-05-27 15:10:00] CPU监控 | 使用率: 92.50% (阈值: 85%)
[2025-05-27 15:10:00] ERROR: CPU使用率超过阈值: 92.50%  // 自动发送邮件告警

六、定时任务配置(Cron)

# 每分钟执行一次监控(root用户)
crontab -e
* * * * * /bin/bash /root/sys_monitor.sh

七、优化建议

  1. 阈值调整:根据服务器配置修改CPU_THRESHOLDLOAD_THRESHOLD等参数
  2. 邮件配置:修改/etc/mail.rc配置真实邮箱信息(支持QQ邮箱、阿里云邮箱等)
  3. 扩展功能:可添加网络带宽监控、进程状态检查等模块

八、完整脚本下载

点击下载系统监控脚本 v2.1

#!/bin/bash
#================================================
# 系统资源监控脚本 v2.1
# 功能:精确监控 + 智能告警 + 可视化输出
#================================================

# 颜色定义
GREEN='\033[0;32m'    # 正常
YELLOW='\033[1;33m'   # 警告
RED='\033[0;31m'      # 严重
BLUE='\033[0;34m'     # 信息
NC='\033[0m'          # 重置颜色

# 配置参数
LOG_FILE="$HOME/sys_monitor.log"   
ALERT_EMAIL="123456@qq.com"
CPU_THRESHOLD=85      # CPU使用率阈值(%)
MEM_THRESHOLD=85      # 内存使用率阈值(%)
DISK_THRESHOLD=85     # 磁盘使用率阈值(%)
LOAD_THRESHOLD=1.5    # 负载系数(负载/核心数)
INTERVAL_SEC=60       # CPU采样间隔(秒)

# 初始化环境
check_commands() {
    local deps=("bc" "mail" "awk")
    for cmd in "${deps[@]}"; do
        command -v "$cmd" >/dev/null 2>&1 || {
            echo -e "${RED}ERROR: 需要安装 $cmd 命令${NC}" >&2
            exit 1
        }
    done
}

# 日志管理
rotate_log() {
    [[ ! -f "$LOG_FILE" ]] && return

    local max_size_mb=10
    local current_size=$(du -m "$LOG_FILE" | awk '{print $1}')
    
    if (( current_size >= max_size_mb )); then
        echo -e "${BLUE}INFO: 日志轮转启动 (当前大小: ${current_size}MB)${NC}"
        for i in {5..1}; do
            [[ -f "${LOG_FILE}.$i" ]] && mv "${LOG_FILE}.$i" "${LOG_FILE}.$((i+1))"
        done
        mv "$LOG_FILE" "${LOG_FILE}.1"
    fi
}

# 增强型日志记录
log() {
    rotate_log
    local timestamp=$(date "+%F %T")
    echo -e "[$timestamp] $1" | tee -a "$LOG_FILE"
}

# 智能颜色标记(支持浮点数)
get_status_color() {
    local value="$1"
    local threshold="$2"
    
    if (( $(echo "$value > $threshold" | bc -l) )); then
        echo "$RED"
    elif (( $(echo "$value > ($threshold - 10)" | bc -l) )); then
        echo "$YELLOW"
    else
        echo "$GREEN"
    fi
}

# 精确CPU监控(1分钟平均)
monitor_cpu() {
    # 第一次采样
    local cpu1=($(awk '/cpu /{print $2+$3+$4+$5+$6+$7+$8,$5}' /proc/stat))
    sleep $INTERVAL_SEC
    # 第二次采样
    local cpu2=($(awk '/cpu /{print $2+$3+$4+$5+$6+$7+$8,$5}' /proc/stat))

    local total_diff=$(( cpu2[0] - cpu1[0] ))
    local idle_diff=$(( cpu2[1] - cpu1[1] ))
    local usage=$(echo "scale=2; 100 - ($idle_diff * 100)/$total_diff" | bc)
    
    local color=$(get_status_color "$usage" "$CPU_THRESHOLD")
    log "CPU监控 | 使用率: ${color}${usage}%${NC} (阈值: ${CPU_THRESHOLD}%)"
    
    if (( $(echo "$usage >= $CPU_THRESHOLD" | bc -l) )); then
        echo "CPU使用率超过阈值: ${usage}%" | mail -s "CPU告警" "$ALERT_EMAIL"
    fi
}

# 内存监控
monitor_memory() {
    local mem_info=($(free -m | awk '/Mem/{print $2,$3}'))
    local usage=$(echo "scale=2; ${mem_info[1]}*100/${mem_info[0]}" | bc)
    
    local color=$(get_status_color "$usage" "$MEM_THRESHOLD")
    log "内存监控 | 使用率: ${color}${usage}%${NC} (阈值: ${MEM_THRESHOLD}%)"
    
    if (( $(echo "$usage >= $MEM_THRESHOLD" | bc -l) )); then
        echo "内存使用率超过阈值: ${usage}%" | mail -s "内存告警" "$ALERT_EMAIL"
    fi
}

# 磁盘监控
monitor_disk() {
    local usage=$(df -h / | awk 'NR==2{sub(/%/, "", $5); print $5}')
    
    local color=$(get_status_color "$usage" "$DISK_THRESHOLD")
    log "磁盘监控 | 使用率: ${color}${usage}%${NC} (阈值: ${DISK_THRESHOLD}%)"
    
    if (( usage >= DISK_THRESHOLD )); then
        echo "磁盘使用率超过阈值: ${usage}%" | mail -s "磁盘告警" "$ALERT_EMAIL"
    fi
}

# 系统负载监控
monitor_load() {
    local cores=$(nproc)
    local load1=$(uptime | awk -F 'load average: ' '{print $2}' | cut -d, -f1 | xargs)
    local ratio=$(echo "scale=2; $load1 / $cores" | bc)
    
    local color=$(get_status_color "$ratio" "$LOAD_THRESHOLD")
    log "负载监控 | 当前值: ${color}${load1}${NC} (核心数: ${cores}, 阈值系数: ${LOAD_THRESHOLD})"
    
    if (( $(echo "$ratio > $LOAD_THRESHOLD" | bc -l) )); then
        echo "系统负载超过阈值: ${load1} (核心数: ${cores})" | mail -s "负载告警" "$ALERT_EMAIL"
    fi
}

# 主执行流程
main() {
    check_commands
    echo -e "\n${BLUE}=== 系统监控启动 [$(date +%F\ %T)] ===${NC}"
    
    monitor_cpu
    monitor_memory
    monitor_disk
    monitor_load
    
    echo -e "${BLUE}=== 监控完成 [$(date +%F\ %T)] ===${NC}\n"
}

# 执行主程序
main

通过该脚本,可实现对服务器资源的实时监控与自动化告警,有效提升系统稳定性和安全性。建议结合具体业务场景进一步定制化开发。

文章版权声明:除非注明,否则均为柳三千运维录原创文章,转载或复制请以超链接形式并注明出处。

取消
微信二维码
微信二维码
支付宝二维码