侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

编写进程资源监控脚本并在超阈值时告警

2025-12-11 / 0 评论 / 3 阅读

题目

编写进程资源监控脚本并在超阈值时告警

信息

  • 类型:问答
  • 难度:⭐⭐

考点

进程监控,资源阈值判断,邮件告警,脚本健壮性

快速回答

该脚本需要实现以下核心功能:

  • 使用pstop获取指定进程的CPU/内存占用
  • 设置可配置的阈值参数
  • 超过阈值时发送告警邮件(使用mail命令)
  • 包含错误处理和参数校验机制

示例命令调用:
./monitor.sh -p nginx -c 50 -m 70 -e admin@example.com

解析

需求分析

需要编写一个可配置的监控脚本,当指定进程的CPU或内存使用率超过预设阈值时,自动发送告警邮件。重点考察:

  • 进程资源获取的准确性
  • 阈值比较逻辑
  • 邮件功能的集成
  • 脚本的健壮性和可配置性

实现方案

基础代码框架

#!/bin/bash

# 默认参数
PROCESS=""
CPU_THRESHOLD=80
MEM_THRESHOLD=90
EMAIL=""

# 解析参数
while getopts ":p:c:m:e:" opt; do
  case $opt in
    p) PROCESS="$OPTARG" ;;
    c) CPU_THRESHOLD="$OPTARG" ;;
    m) MEM_THRESHOLD="$OPTARG" ;;
    e) EMAIL="$OPTARG" ;;
    ?) echo "Invalid option: -$OPTARG"; exit 1 ;;
  esac
done

# 参数校验
if [ -z "$PROCESS" ] || [ -z "$EMAIL" ]; then
  echo "Usage: $0 -p process_name -e email [-c cpu_threshold] [-m mem_threshold]"
  exit 1
fi

# 获取进程资源使用率
pid=$(pgrep -f "$PROCESS" | head -1)
if [ -z "$pid" ]; then
  echo "ERROR: Process '$PROCESS' not found"
  exit 1
fi

# 使用ps获取CPU和内存百分比
stats=$(ps -p "$pid" -o %cpu,%mem --no-headers)
cpu_usage=$(echo "$stats" | awk '{print $1}')
mem_usage=$(echo "$stats" | awk '{print $2}')

# 浮点数比较(使用bc)
cpu_alert=$(echo "$cpu_usage > $CPU_THRESHOLD" | bc -l)
mem_alert=$(echo "$mem_usage > $MEM_THRESHOLD" | bc -l)

# 告警逻辑
if [ "$cpu_alert" -eq 1 ] || [ "$mem_alert" -eq 1 ]; then
  subject="ALERT: $PROCESS resource usage exceeded"
  body="Process: $PROCESS (PID: $pid)\n"
  body+="CPU Usage: ${cpu_usage}% (Threshold: ${CPU_THRESHOLD}%)\n"
  body+="Memory Usage: ${mem_usage}% (Threshold: ${MEM_THRESHOLD}%)"

  echo -e "$body" | mail -s "$subject" "$EMAIL"
  echo "Alert sent to $EMAIL"
fi

关键点说明

1. 资源获取方式

  • 使用ps -p pid -o %cpu,%mem获取特定进程资源
  • 替代方案:top -b -n1 -p pid(需额外解析)
  • 注意%cpu是累计CPU时间除以进程运行时间,可能超过100%(多核场景)

2. 浮点数比较

  • Shell本身不支持浮点比较,需借助bcawk
  • 示例:echo "$cpu_usage > 50.5" | bc -l 返回1(true)或0(false)

3. 邮件发送

  • 依赖系统mail命令,需提前配置SMTP
  • 替代方案:sendmailssmtp
  • 最佳实践:邮件主题包含关键信息,正文结构化

4. 健壮性增强

  • 使用getopts处理参数,支持带空格的进程名
  • 检查进程是否存在:pgrep -f匹配完整命令
  • 验证数值参数:添加[ "$CPU_THRESHOLD" -eq "$CPU_THRESHOLD" ] 2>/dev/null

常见错误

  • 进程匹配问题:使用pgrep而非ps | grep避免匹配到grep自身
  • 多进程处理:当前脚本监控第一个匹配进程,应循环处理所有PID:
    pgrep -f "$PROCESS" | while read pid; do
      # 监控每个pid
      stats=$(ps -p "$pid" -o %cpu,%mem --no-headers)
      ...
    done
  • 阈值类型错误:未校验参数是否为数字,导致bc报错

扩展优化

  • 频率控制:添加时间戳记录,避免重复告警
  • 多监控项:增加磁盘IO、线程数等监控
  • 聚合报告:改为周期性运行,生成汇总报告
  • 替代工具:生产环境建议使用Prometheus+Grafana等专业方案

完整增强版示例

#!/bin/bash

# 添加参数校验函数
validate_number() {
  if ! [[ "$2" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then
    echo "ERROR: Invalid $1 value '$2'"
    exit 1
  fi
}

# 解析参数(略)...

# 增强校验
validate_number "CPU threshold" "$CPU_THRESHOLD"
validate_number "Memory threshold" "$MEM_THRESHOLD"

# 获取所有匹配进程
pids=$(pgrep -f "$PROCESS")
if [ -z "$pids" ]; then
  echo "ERROR: Process '$PROCESS' not running"
  exit 1
fi

# 监控每个进程
while read pid; do
  stats=$(ps -p "$pid" -o %cpu,%mem,cmd --no-headers)
  # 解析数据(略)...

  # 触发告警(略)...
done <<< "$pids"