使用-Shell-脚本监控服务器-IOWait-并发送邮件告警
目录
使用 Shell 脚本监控服务器 IOWait 并发送邮件告警
前言
在生产环境中,磁盘 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" ]; then
echo "iowait值为空"
exit 0
else
#判断是否大于阈值,大于则发送邮件告警
if awk "BEGIN {exit !($iowait > $IOWAIT_WARNING)}"; then
warning_info="${TIME}
主机: $(hostname)
iowait当前值为: ${iowait}%
已超过阈值: ${IOWAIT_WARNING}%"
(
echo "Subject: $TITLE"
echo "To: $MAIL_TO"
echo
echo -e "$warning_info"
) | msmtp -t
else
echo "iowait值正常"
fi
fi脚本说明
变量说明:
IOWAIT_WARNING:告警阈值,可在测试时设置负数强制触发MAIL_TO:收件人,多收件人空格分隔TITLE:邮件标题
邮件发送:
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 多收件人邮件只收到了部分邮箱
原因:
- SMTP 服务器限制,只允许发给同域邮箱
- 收件人不存在或拼写错误
- 邮件头
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=0→exit 0
shellif看到退出码 0,认为真,进入 then。 - 假设
$iowait≤$THRESHOLD→ 表达式值0→!0=1→exit 1
shellif看到退出码 1,认为假,跳过 then。
所以这句相当于:
“如果
$iowait大于$THRESHOLD,awk 以状态码 0 退出(shell if 真);
否则 awk 以状态码 1 退出(shell if 假)。”
5. 总结
- 使用 Shell 脚本 +
iostat可以轻松监控服务器 IO Wait - 告警邮件可用
msmtp或mailx发送,多收件人需注意 SMTP 限制 - 浮点比较、空值检查和邮件头书写是脚本稳定性的关键点