文章最后更新时间: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
七、优化建议
- 阈值调整:根据服务器配置修改
CPU_THRESHOLD
、LOAD_THRESHOLD
等参数 - 邮件配置:修改
/etc/mail.rc
配置真实邮箱信息(支持QQ邮箱、阿里云邮箱等) - 扩展功能:可添加网络带宽监控、进程状态检查等模块
八、完整脚本下载
#!/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
通过该脚本,可实现对服务器资源的实时监控与自动化告警,有效提升系统稳定性和安全性。建议结合具体业务场景进一步定制化开发。
文章版权声明:除非注明,否则均为柳三千运维录原创文章,转载或复制请以超链接形式并注明出处。