前言
在生产环境中,磁盘 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 限制浮点比较、空值检查和邮件头书写是脚本稳定性的关键点