Shell 脚本实现系统监控与告警
Shell 脚本实现系统监控与告警
文章目录
- Shell 脚本实现系统监控与告警
- 一、脚本整体设计
- 二、脚本文件(system_monitor.sh)
- 三、前置准备(必做)
- 1. 安装依赖工具
- 2. 配置SMTP邮件服务
- 四、脚本使用步骤
- 五、关键说明
- 六、常见问题排查
以下是一套完整的系统监控Shell脚本,包含CPU、内存、硬盘、IO、网络流量监控及邮件告警功能,支持配置化调整阈值,便于维护和扩展。
一、脚本整体设计
- 配置与告警分离:将监控阈值、邮件参数等配置项集中管理,便于修改。
- 模块化监控:按“CPU/内存/硬盘/IO/网络”拆分监控逻辑,结构清晰。
- 邮件告警优化:支持HTML格式邮件,告警信息排版清晰,附带监控时间和主机信息。
- 兼容性:适配CentOS/Ubuntu等主流Linux发行版(依赖
vmstat
、iostat
、ifstat
等工具,需提前安装)。
二、脚本文件(system_monitor.sh)
#!/bin/bash
# 系统监控脚本:CPU/内存/硬盘/IO/网络流量监控 + 邮件告警
# 依赖工具:vmstat, iostat, ifstat, df, free, grep, awk, sendmail/postfix##############################################################################
# 1. 配置区(根据实际需求修改以下参数)
##############################################################################
# 监控阈值配置
CPU_THRESHOLD=80 # CPU使用率阈值(%)
MEM_THRESHOLD=80 # 内存使用率阈值(%)
DISK_THRESHOLD=80 # 硬盘使用率阈值(%)
IO_AWAIT_THRESHOLD=50 # IO等待时间阈值(ms)
NET_THRESHOLD=10 # 网络流量阈值(Mbps,上传+下载)# 邮件告警配置
SMTP_SERVER="smtp.qq.com" # SMTP服务器(如QQ邮箱:smtp.qq.com,163邮箱:smtp.163.com)
SMTP_PORT=587 # SMTP端口(QQ/163常用587或465)
SMTP_USER="your_email@qq.com" # 发件人邮箱
SMTP_PASS="your_auth_code" # 邮箱授权码(非登录密码,需在邮箱设置中开启SMTP并获取)
ALERT_EMAIL="alert_target@example.com" # 告警接收邮箱# 其他配置
MONITOR_INTERVAL=60 # 监控间隔(秒),建议60秒以上避免频繁告警
NETWORK_INTERFACE="eth0" # 监控的网络接口(用`ifconfig`查看,如eth0、ens33、wlan0)
HOSTNAME=$(hostname) # 主机名(用于告警邮件标识)
CURRENT_TIME=$(date "+%Y-%m-%d %H:%M:%S") # 当前时间##############################################################################
# 2. 工具依赖检查
##############################################################################
check_dependencies() {local dependencies=("vmstat" "iostat" "ifstat" "sendmail" "awk" "grep" "free" "df")for tool in "${dependencies[@]}"; doif ! command -v $tool &> /dev/null; thenecho "错误:缺少依赖工具 $tool,请先安装!"exit 1fidone
}##############################################################################
# 3. 邮件发送函数(HTML格式,支持中文)
##############################################################################
send_alert_email() {local subject="$1"local content="$2"# 构造邮件内容(HTML格式,支持换行和加粗)local email_body="
From: $SMTP_USER
To: $ALERT_EMAIL
Subject: $subject
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8<html>
<head><title>系统监控告警</title></head>
<body>
<h3>⚠️ 主机 $HOSTNAME 告警通知</h3>
<p>告警时间:$CURRENT_TIME</p>
<p>告警详情:</p>
$content
</body>
</html>"# 通过sendmail发送邮件(需提前配置好SMTP服务,如postfix+sendmail)echo -e "$email_body" | sendmail -v $ALERT_EMAILif [ $? -eq 0 ]; thenecho "[$CURRENT_TIME] 告警邮件已发送至 $ALERT_EMAIL"elseecho "[$CURRENT_TIME] 告警邮件发送失败!"fi
}##############################################################################
# 4. 监控模块:CPU使用率
##############################################################################
monitor_cpu() {# 通过vmstat获取CPU使用率(idle为空闲率,100-idle即为使用率)local cpu_idle=$(vmstat 1 2 | tail -1 | awk '{print $15}')local cpu_usage=$((100 - cpu_idle))echo "[$CURRENT_TIME] CPU使用率:$cpu_usage%"if [ $cpu_usage -ge $CPU_THRESHOLD ]; thenlocal subject="【系统告警】CPU使用率超标"local content="<p>🔹 当前CPU使用率:<b>$cpu_usage%</b></p><p>🔹 阈值:$CPU_THRESHOLD%</p>"send_alert_email "$subject" "$content"fi
}##############################################################################
# 5. 监控模块:内存使用率
##############################################################################
monitor_memory() {# 通过free获取内存信息(单位:KB)local mem_total=$(free -k | grep Mem | awk '{print $2}')local mem_used=$(free -k | grep Mem | awk '{print $3}')# 计算使用率(四舍五入取整)local mem_usage=$(( (mem_used * 100 + mem_total / 2) / mem_total ))echo "[$CURRENT_TIME] 内存使用率:$mem_usage%"if [ $mem_usage -ge $MEM_THRESHOLD ]; thenlocal subject="【系统告警】内存使用率超标"local content="<p>🔹 当前内存使用率:<b>$mem_usage%</b></p><p>🔹 阈值:$MEM_THRESHOLD%</p><p>🔹 总内存:$((mem_total/1024))MB,已用:$((mem_used/1024))MB</p>"send_alert_email "$subject" "$content"fi
}##############################################################################
# 6. 监控模块:硬盘使用率
##############################################################################
monitor_disk() {# 监控所有挂载的硬盘分区(排除tmpfs等虚拟文件系统)local disk_info=$(df -hP | grep -vE 'tmpfs|udev|loop' | awk '{print $6,$5}')echo "[$CURRENT_TIME] 硬盘分区使用率:"echo "$disk_info" | while read -r mount_point usage; do# 去掉使用率的"%"符号,转为数字local usage_num=${usage%\%}echo " - $mount_point:$usage"if [ $usage_num -ge $DISK_THRESHOLD ]; thenlocal subject="【系统告警】硬盘使用率超标"local content="<p>🔹 分区:<b>$mount_point</b></p><p>🔹 当前使用率:<b>$usage</b></p><p>🔹 阈值:$DISK_THRESHOLD%</p>"send_alert_email "$subject" "$content"fidone
}##############################################################################
# 7. 监控模块:IO等待时间(await)
##############################################################################
monitor_io() {# 通过iostat获取IO信息(await:平均等待时间,单位ms)# 取2次采样(间隔1秒),避免瞬时值干扰local io_await=$(iostat -x 1 2 | grep -A1 "^Device" | tail -1 | awk '{print $10}')# 转为整数(四舍五入)local io_await_int=$(printf "%.0f" "$io_await")echo "[$CURRENT_TIME] IO平均等待时间:$io_await_int ms"if [ $io_await_int -ge $IO_AWAIT_THRESHOLD ]; thenlocal subject="【系统告警】IO等待时间超标"local content="<p>🔹 当前IO等待时间:<b>$io_await_int ms</b></p><p>🔹 阈值:$IO_AWAIT_THRESHOLD ms</p>"send_alert_email "$subject" "$content"fi
}##############################################################################
# 8. 监控模块:网络流量(上传+下载)
##############################################################################
monitor_network() {# 通过ifstat获取指定接口的流量(单位:KB/s)# 取2次采样(间隔1秒),计算平均速率local net_stats=$(ifstat -i $NETWORK_INTERFACE 1 2 | grep -v "^ " | tail -1)local download_kbps=$(echo "$net_stats" | awk '{print $1}') # 下载速率(KB/s)local upload_kbps=$(echo "$net_stats" | awk '{print $2}') # 上传速率(KB/s)# 转为Mbps(1Mbps = 128KB/s),四舍五入取1位小数local download_mbps=$(printf "%.1f" "$(echo "$download_kbps / 128" | bc -l)")local upload_mbps=$(printf "%.1f" "$(echo "$upload_kbps / 128" | bc -l)")local total_mbps=$(printf "%.1f" "$(echo "$download_mbps + $upload_mbps" | bc -l)")echo "[$CURRENT_TIME] 网络流量($NETWORK_INTERFACE):"echo " - 下载:$download_mbps Mbps,上传:$upload_mbps Mbps,总计:$total_mbps Mbps"# 转为整数比较(避免小数精度问题)local total_int=$(printf "%.0f" "$total_mbps")if [ $total_int -ge $NET_THRESHOLD ]; thenlocal subject="【系统告警】网络流量超标"local content="<p>🔹 接口:<b>$NETWORK_INTERFACE</b></p><p>🔹 总流量:<b>$total_mbps Mbps</b></p><p>🔹 下载:$download_mbps Mbps,上传:$upload_mbps Mbps</p><p>🔹 阈值:$NET_THRESHOLD Mbps</p>"send_alert_email "$subject" "$content"fi
}##############################################################################
# 9. 主执行函数
##############################################################################
main() {echo "======================================"echo "系统监控脚本启动(主机:$HOSTNAME)"echo "监控间隔:$MONITOR_INTERVAL 秒"echo "阈值配置:CPU=$CPU_THRESHOLD% | 内存=$MEM_THRESHOLD% | 硬盘=$DISK_THRESHOLD% | IO等待=$IO_AWAIT_THRESHOLD ms | 网络=$NET_THRESHOLD Mbps"echo "======================================"# 先检查依赖工具check_dependencies# 循环执行监控(无限循环,可通过Ctrl+C停止)while true; doecho -e "\n--------------------------------------"monitor_cpumonitor_memorymonitor_diskmonitor_iomonitor_networkecho "--------------------------------------"echo "等待 $MONITOR_INTERVAL 秒后再次监控..."sleep $MONITOR_INTERVALdone
}# 启动主函数
main
三、前置准备(必做)
1. 安装依赖工具
脚本依赖以下工具,需提前安装:
# CentOS/RHEL
yum install -y sysstat ifstat sendmail postfix bc# Ubuntu/Debian
apt update && apt install -y sysstat ifstat sendmail postfix bc
2. 配置SMTP邮件服务
脚本通过sendmail
发送邮件,需配置SMTP服务(以QQ邮箱为例):
- 登录QQ邮箱 → 【设置】→ 【账户】→ 开启“POP3/SMTP服务”,获取授权码(不是登录密码)。
- 配置postfix的SMTP中继(以QQ邮箱为例):
添加以下配置(替换为你的邮箱信息):# 编辑postfix配置文件 vi /etc/postfix/main.cf
relayhost = [smtp.qq.com]:587 # SMTP服务器及端口 smtp_use_tls = yes smtp_tls_CAfile = /etc/pki/tls/certs/ca-bundle.crt smtp_sasl_auth_enable = yes smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd smtp_sasl_security_options = noanonymous
- 创建SMTP密码文件:
echo "[smtp.qq.com]:587 your_email@qq.com:your_auth_code" > /etc/postfix/sasl_passwd chmod 600 /etc/postfix/sasl_passwd postmap /etc/postfix/sasl_passwd
- 重启postfix和sendmail服务:
systemctl restart postfix sendmail systemctl enable postfix sendmail
四、脚本使用步骤
- 修改配置:打开
system_monitor.sh
,根据实际需求修改“配置区”参数(尤其是邮件信息和网络接口)。 - 添加执行权限:
chmod +x system_monitor.sh
- 测试运行:
观察输出是否正常,可通过./system_monitor.sh
dd if=/dev/zero of=/tmp/test bs=1G count=1
等命令模拟高负载测试告警。 - 后台运行(推荐):
为避免终端关闭后脚本停止,使用nohup
后台运行:
日志会输出到nohup ./system_monitor.sh > /var/log/system_monitor.log 2>&1 &
/var/log/system_monitor.log
,便于后续排查。
五、关键说明
- 阈值调整:网络流量阈值
NET_THRESHOLD
可根据实际带宽调整(单位:Mbps),例如100Mbps带宽可设为80。 - IO等待时间:
iostat
的await
指标反映IO请求的平均等待时间(包括队列等待和处理时间),大于50ms通常表示IO压力较大。 - 告警频率:脚本按
MONITOR_INTERVAL
间隔监控,若阈值持续超标,会每次都发送告警。如需“告警抑制”(如5分钟内只发一次),可在发送邮件前添加文件锁判断(例如创建临时文件,5分钟后删除)。 - 多接口监控:若需监控多个网络接口,可将
NETWORK_INTERFACE
改为数组(如("eth0" "eth1")
),并修改monitor_network
函数为循环遍历接口。
六、常见问题排查
- 邮件发送失败:
- 检查postfix日志:
tail -f /var/log/maillog
。 - 确认SMTP授权码正确,且未开启“异地登录保护”。
- 检查postfix日志:
- IO监控无数据:确保
sysstat
已安装,且内核支持IO统计(iostat -x
有输出则正常)。 - 网络流量为0:确认
NETWORK_INTERFACE
参数与实际接口名称一致(用ifconfig
或ip addr
查看)。
通过以上脚本,可实现对系统关键指标的实时监控和及时告警,保障系统稳定运行。