当前位置: 首页 > ai >正文

使用 Shell 脚本监控服务器 IOWait 并发送邮件告警

前言

1. IO Wait 简介

2. 获取 IOWait 的方法

3. Shell 脚本实现

脚本说明

4. 常见问题与解决

4.1 iowait 取到空值

4.2 awk 比较浮点数报错

4.3 多收件人邮件只收到了部分邮箱

4.4 测试告警

5. 总结

前言

在生产环境中,磁盘 IO 瓶颈是影响服务器性能的重要因素之一。本文介绍如何用 Shell 脚本监控 IO Wait,并在超过阈值时通过邮箱告警,同时讨论多收件人和邮件发送中常见的问题及解决方法。


1. IO Wait 简介

  • IOWait 是 CPU 等待磁盘或网络 IO 完成的时间百分比。

  • 当 IOWait 高于阈值时,意味着系统可能出现 IO 瓶颈,需要关注磁盘性能。


2. 获取 IOWait 的方法

我们使用 iostat 命令获取 CPU IO Wait 值:

iostat -cy 1 1 | awk '/^ /{print $4}'

说明:

  • -c:显示 CPU 使用情况

  • -y:跳过平均值(可选)

  • 1 1:每隔 1 秒采样一次,只输出一次

  • awk '/^ /{print $4}':匹配数据行,取第 4 列(%iowait)

注意:不能直接用 awk 'END{print $4}',因为最后一行可能是空行或表头,导致取到空值。


3. Shell 脚本实现

下面是一个完整示例,带告警邮件功能:

#!/bin/bash#设置阈值(设置负数用于测试)
IOWAIT_WARNING=-1#设置邮件收件人
MAIL_TO="3426848201@qq.com,2270993679@qq.com"#邮件标题
TITLE="服务器IO等待告警"#iowait获取
iowait=$(iostat -cy 1 1 | awk '/^ /{print $4}')#获取当前系统时间
TIME=$(date +"%F %T")#判断iowait是否为空,防止误报
if [ -z "$iowait" ]; thenecho "iowait值为空"exit 0
else#判断是否大于阈值,大于则发送邮件告警if awk "BEGIN {exit !($iowait > $IOWAIT_WARNING)}"; thenwarning_info="${TIME}主机: $(hostname)iowait当前值为: ${iowait}%已超过阈值: ${IOWAIT_WARNING}%"(echo "Subject: $TITLE"echo "To: $MAIL_TO"echoecho -e "$warning_info") | msmtp -telseecho "iowait值正常" fi
fi

脚本说明

  1. 变量说明

    • IOWAIT_WARNING:告警阈值,可在测试时设置负数强制触发

    • MAIL_TO:收件人,多收件人空格分隔

    • TITLE:邮件标题

  2. 邮件发送

    • msmtp -t 从邮件头读取收件人 To: 和标题 Subject:

    • 如果在 /etc/msmtprc 已配置 from,脚本中无需再写 From:

    • 多收件人时最好用空格或逗号分隔,但不同 SMTP 对空格/逗号解析可能不同,必要时分开发送。


4. 常见问题与解决

4.1 iowait 取到空值

  • 原因:awk 'END{print $4}' 可能取到空行或表头

  • 解决:使用 /^ /{v=$4} END{print v} 或直接 iostat -cy 1 1 | awk '/^ /{print $4}'


4.2 awk 比较浮点数报错

  • 原因:小数点在 Shell 展开时可能导致语法错误

  • 解决:使用 awk -v io="$iowait" -v th="$IOWAIT_WARNING" 传入变量

     补充:

  • -v io="$iowait"
    把 shell 变量 $iowait 传给 awk 内部变量 io

  • -v th="$IOWAIT_WARNING"
    把阈值 $IOWAIT_WARNING 传给 awk 内部变量 th

  • 'BEGIN {exit !(io > th)}'

    • BEGIN 块在 awk 开始处理任何输入之前执行

    • io > th 为真时,!(io > th) 为假,exit 0 → awk 返回成功

    • io > th 为假时,!(io > th) 为真,exit 1 → awk 返回失败


4.3 多收件人邮件只收到了部分邮箱

  • 原因:

    1. SMTP 服务器限制,只允许发给同域邮箱

    2. 收件人不存在或拼写错误

    3. 邮件头 To: 与 SMTP 命令行不匹配

  • 解决:

    • 确保邮箱有效

    • 使用 msmtp -t 并在 To: 中列出所有收件人

    • 测试时可先用同域邮箱确保收全


4.4 测试告警

  • 可以将阈值设为负数,或临时把 $iowait 赋值为大于阈值的值,强制触发邮件发送逻辑:

iowait=99.99

4.5 补充知识

awk 的退出码与 shell 的 if

  • shell 在执行一条命令后,可以通过 $? 取到退出状态

  • if 判断的是真假:退出状态为 0 表示“真”(success),非 0 表示“假”(failure)。

  • awk 程序里执行 exit N,退出码就是 N,shell 能接收到。


 awk 里布尔运算

  • 在 awk 中,布尔表达式 ($iowait > $THRESHOLD) 的值是真或假:
    1
    0

  • ! 是逻辑非运算符:
    !1 = 0
    !0 = 1


为什么写 exit !($iowait > $THRESHOLD)

逐步展开:

  • 假设 $iowait > $THRESHOLD → 表达式值 1!1 = 0exit 0
    shell if 看到退出码 0,认为真,进入 then。

  • 假设 $iowait$THRESHOLD → 表达式值 0!0 = 1exit 1
    shell if 看到退出码 1,认为假,跳过 then。

所以这句相当于:

“如果 $iowait 大于 $THRESHOLD,awk 以状态码 0 退出(shell if 真);
否则 awk 以状态码 1 退出(shell if 假)。”


5. 总结

  • 使用 Shell 脚本 + iostat 可以轻松监控服务器 IO Wait

  • 告警邮件可用 msmtpmailx 发送,多收件人需注意 SMTP 限制

  • 浮点比较、空值检查和邮件头书写是脚本稳定性的关键点

http://www.xdnf.cn/news/20212.html

相关文章:

  • Python带状态生成器完全指南:从基础到高并发系统设计
  • C#实现导入CSV数据到List<T>的完整教程
  • 【基础-单选】用哪一种装饰器修饰的struct表示该结构体具有组件化能力?
  • Playwright携手MCP:AI智能体实现自主化UI回归测试
  • 第26节:GPU加速计算与Compute Shader探索
  • Homebrew执行brew install出现错误(homebrew-bottles)
  • Go语言后端开发面试实战:谢飞机的“硬核”面试之旅
  • CodeBuddy 辅助重构:去掉 800 行 if-else 的状态机改造
  • Eclipse下的一些快捷键备忘录
  • LangChain实战(十九):集成OpenAI Functions打造强大Agent
  • Day37 MQTT协议 多客户端服务器模型
  • 手写MyBatis第53弹: @Intercepts与@Signature注解的工作原理
  • 工业洗地机和商用洗地机的区别是什么?
  • 【基础-单选】关于bundleName,下列说法正确的是?
  • 波特率vs比特率
  • rh134第三章复习总结
  • 贪心算法应用:保险理赔调度问题详解
  • Java中的死锁
  • 使用 MongoDB.Driver 在 C# .NETCore 中实现 Mongo DB 过滤器
  • [数据结构] ArrayList(顺序表)与LinkedList(链表)
  • 万代《宝可梦》主题新品扭蛋公开!史上最大尺寸
  • 机器人控制器开发(传感器层——奥比大白相机适配)
  • 【FastDDS】Layer Transport ( 05-Shared Memory Transport)
  • 天气预报云服务器部署实战
  • 在Java AI项目中实现Function Call功能
  • 计算机毕设大数据方向:基于Spark+Hadoop的餐饮外卖平台数据分析系统【源码+文档+调试】
  • 通过Idea 阿里插件快速部署java jar包
  • 实用向:Linux Shell 脚本实现 CPU / 内存 / 硬盘 + IO / 网络多指标告警(支持 163/QQ/139 邮箱)
  • python调用mysql
  • PDF文件基础-计算机字体