Linux系统资源监控脚本
文章目录
- 手把手打造Linux系统资源监控脚本:CPU/内存/磁盘/IO/网络全覆盖,msmtp邮件告警
- 一、脚本核心功能与依赖准备
- 1. 核心监控维度
- 2. 依赖工具安装
- 二、msmtp邮件配置(关键步骤)
- 1. 开启邮箱SMTP服务
- 2. 编写msmtp配置文件
- 3. 测试msmtp是否可用
- 三、监控脚本完整代码与解析
- 1. 完整脚本代码
- 2. 脚本关键部分解析
- (1)配置区:灵活调整参数
- (2)资源监控:避免命令依赖报错
- (3)邮件发送:静默模式更友好
- 四、脚本使用与自动化部署
- 1. 脚本执行与测试
- 2. 配置定时任务(crontab)
- 五、常见问题排查
- 六、脚本扩展建议
手把手打造Linux系统资源监控脚本:CPU/内存/磁盘/IO/网络全覆盖,msmtp邮件告警
在Linux服务器运维中,实时监控系统资源状态是保障服务稳定的关键。当CPU使用率飙升、内存耗尽或磁盘满了时,若不能及时发现,很可能导致服务崩溃。今天就带大家从零开始,编写一个全维度资源监控脚本,支持CPU、内存、磁盘、IO等待、网络流量监控,且能通过msmtp发送邮件告警,让运维更高效。
一、脚本核心功能与依赖准备
在开始编写前,先明确脚本的核心能力和所需依赖,避免后续踩坑。
1. 核心监控维度
- CPU使用率:阈值可自定义(默认80%),超阈值触发告警
- 内存使用率:计算已用内存占比(默认阈值80%)
- 根分区磁盘:监控容量使用率、总容量、剩余空间(默认阈值10%,可按需调整)
- IO等待时间:通过iostat获取磁盘IO响应延迟(默认阈值50ms)
- 网络流量:监控指定网卡的上传/下载速率(默认阈值10MB/s)
- 邮件告警:用msmtp发送含详细资源信息的邮件,支持正常/异常状态区分
2. 依赖工具安装
脚本需要用到系统监控工具和邮件发送工具,以CentOS/RHEL为例(Ubuntu/Debian将yum
替换为apt
):
# 安装系统监控工具(iostat、free、df等)
yum install -y sysstat procps-ng
# 安装msmtp邮件发送工具
yum install -y msmtp
二、msmtp邮件配置(关键步骤)
脚本依赖msmtp发送邮件,需先配置邮箱账号(以QQ邮箱为例,163/139邮箱配置类似)。
1. 开启邮箱SMTP服务
- 登录QQ邮箱,进入「设置」→「账户」
- 找到「POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务」,开启「SMTP服务」
- 生成「授权码」(不是邮箱密码!),保存备用
2. 编写msmtp配置文件
创建/etc/msmtprc
配置文件,填入以下内容(替换成你的信息):
# 账户默认配置
account default
# QQ邮箱SMTP服务器(端口465用SSL,25用非SSL,推荐465)
host smtp.qq.com
port 465
# 发件人邮箱(你的QQ邮箱)
from 123456@qq.com
# 认证开启
auth on
# 认证用户名(同发件人邮箱)
user 123456@qq.com
# 邮箱授权码(不是密码!)
password abcdefghijklmnop
# 启用SSL加密(端口465必须开启)
tls on
# 忽略证书验证(避免因证书问题发送失败)
tls_starttls off
tls_certcheck off
# 日志文件(可选,用于排查发送问题)
logfile /var/log/msmtp.log
3. 测试msmtp是否可用
配置完成后,先手动测试邮件发送,确保msmtp正常工作:
# 发送测试邮件(替换收件人邮箱)
echo -e "Subject: 测试邮件\n\n这是监控脚本的测试邮件" | msmtp 3185822875@qq.com
若收件人能收到邮件,说明msmtp配置成功;若失败,可查看/var/log/msmtp.log
日志排查问题(如授权码错误、端口被封)。
三、监控脚本完整代码与解析
脚本分为「配置区」「资源监控逻辑」「邮件发送」三部分,结构清晰,便于后续修改阈值或扩展功能。
1. 完整脚本代码
创建system_monitor.sh
文件,复制以下代码:
#!/bin/bash###########################################################################
# 1. 核心配置区(可根据需求修改)
###########################################################################
# 告警阈值
CPU_THRESHOLD=80 # CPU使用率阈值(%)
MEM_THRESHOLD=80 # 内存使用率阈值(%)
DISK_THRESHOLD=80 # 根分区磁盘使用率阈值(%)
IO_THRESHOLD=50 # IO await阈值(毫秒)
NET_THRESHOLD=10 # 网络流量阈值(MB/s)
INTERFACE="ens33" # 监控的网卡(用ls /sys/class/net/查看实际网卡名)
EMAIL="1111111111@qq.com" # 收件人邮箱(改为你自己的qq邮箱)# 日志配置
LOG_FILE="/tmp/monitor_final.log" # 监控日志
DEBUG_LOG="/tmp/msmtp_debug.log" # 邮件调试日志(仅错误时记录)###########################################################################
# 2. 基础信息初始化
###########################################################################
HOSTNAME=$(hostname) # 主机名
CURRENT_TIME=$(date "+%Y-%m-%d %H:%M:%S") # 当前时间
ALERT_MSG="" # 告警信息存储变量###########################################################################
# 3. 资源监控逻辑(逐维度获取数据并判断是否告警)
###########################################################################
# 3.1 监控CPU使用率
# top命令获取CPU使用率(用户态+系统态),printf转为整数
CPU_USAGE=$(top -b -n 1 | grep "Cpu(s)" | awk '{print $2 + $4}')
CPU_USAGE_INT=$(printf "%.0f" "$CPU_USAGE")
# 超阈值则添加告警信息
if [ "$CPU_USAGE_INT" -gt "$CPU_THRESHOLD" ]; thenALERT_MSG="$ALERT_MSG- CPU使用率告警:$CPU_USAGE_INT%(阈值:$CPU_THRESHOLD%)"
fi# 3.2 监控内存使用率
# free命令获取内存总量、已用、空闲,计算使用率
MEM_TOTAL=$(free -m | awk '/Mem:/ {print $2}') # 总内存(MB)
MEM_USED=$(free -m | awk '/Mem:/ {print $3}') # 已用内存(MB)
MEM_FREE=$(free -m | awk '/Mem:/ {print $4}') # 空闲内存(MB)
if [ "$MEM_TOTAL" -gt 0 ]; thenMEM_USAGE=$((MEM_USED * 100 / MEM_TOTAL)) # 内存使用率(%)if [ "$MEM_USAGE" -gt "$MEM_THRESHOLD" ]; thenALERT_MSG="$ALERT_MSG- 内存使用率告警:$MEM_USAGE%(阈值:$MEM_THRESHOLD%)"fi
fi# 3.3 监控根分区磁盘
# df命令获取根分区信息,sed移除百分号
DISK_USAGE=$(df -h / | awk '/\// {print $5}' | sed 's/%//g') # 使用率(%)
DISK_TOTAL=$(df -h / | awk '/\// {print $2}') # 总容量(如50G)
DISK_USED=$(df -h / | awk '/\// {print $3}') # 已用容量
DISK_FREE=$(df -h / | awk '/\// {print $4}') # 剩余容量
if [ "$DISK_USAGE" -gt "$DISK_THRESHOLD" ]; thenALERT_MSG="$ALERT_MSG- 磁盘使用率告警:$DISK_USAGE%(阈值:$DISK_THRESHOLD%,分区:/)"
fi# 3.4 监控IO等待时间
# 先判断iostat是否安装,避免命令不存在报错
if command -v iostat &> /dev/null; thenIO_AWAIT=$(iostat | awk '/^sda/ {print $10}') # 获取sda磁盘的IO等待时间IO_AWAIT_INT=$(printf "%.0f" "$IO_AWAIT")if [ "$IO_AWAIT_INT" -gt "$IO_THRESHOLD" ]; thenALERT_MSG="$ALERT_MSG- IO await告警:$IO_AWAIT_INT ms(阈值:$IO_THRESHOLD ms)"fi
elseIO_AWAIT_INT="N/A (iostat未安装)"ALERT_MSG="$ALERT_MSG- 警告:未安装iostat,无法监控IO状态"
fi# 3.5 监控网络流量
# 读取网卡1秒前后的字节数,计算每秒速率(转为MB/s)
if [ -d "/sys/class/net/$INTERFACE" ]; thenRX_BYTES1=$(cat /sys/class/net/$INTERFACE/statistics/rx_bytes) # 初始下载字节TX_BYTES1=$(cat /sys/class/net/$INTERFACE/statistics/tx_bytes) # 初始上传字节sleep 1 # 等待1秒RX_BYTES2=$(cat /sys/class/net/$INTERFACE/statistics/rx_bytes) # 1秒后下载字节TX_BYTES2=$(cat /sys/class/net/$INTERFACE/statistics/tx_bytes) # 1秒后上传字节# 计算速率(字节→MB:除以1024*1024)RX_RATE=$(( (RX_BYTES2 - RX_BYTES1) / 1024 / 1024 )) # 下载速率(MB/s)TX_RATE=$(( (TX_BYTES2 - TX_BYTES1) / 1024 / 1024 )) # 上传速率(MB/s)if [ "$RX_RATE" -gt "$NET_THRESHOLD" ]; thenALERT_MSG="$ALERT_MSG- 下载流量告警:$RX_RATE MB/s(阈值:$NET_THRESHOLD MB/s)"fiif [ "$TX_RATE" -gt "$NET_THRESHOLD" ]; thenALERT_MSG="$ALERT_MSG- 上传流量告警:$TX_RATE MB/s(阈值:$NET_THRESHOLD MB/s)"fi
elseALERT_MSG="$ALERT_MSG- 网络接口异常:$INTERFACE 不存在"RX_RATE="N/A"TX_RATE="N/A"
fi###########################################################################
# 4. 邮件发送逻辑(静默模式,仅显示结果不显示过程)
###########################################################################
# 给未定义变量设默认值(避免空值报错)
MEM_USAGE=${MEM_USAGE:-0}
IO_AWAIT_INT=${IO_AWAIT_INT:-0}# 区分邮件主题(异常/正常)
if [ -n "$ALERT_MSG" ]; thenSUBJECT="【系统告警】$HOSTNAME 资源异常 - $CURRENT_TIME"
elseSUBJECT="【系统监控】$HOSTNAME 资源正常 - $CURRENT_TIME"
fi# 邮件正文(含所有资源详情,格式清晰)
BODY="系统资源监控详情
=============================
主机名:$HOSTNAME
监控时间:$CURRENT_TIME
=============================
1. CPU状态- 当前使用率:$CPU_USAGE_INT%- 告警阈值:$CPU_THRESHOLD%2. 内存状态- 当前使用率:$MEM_USAGE%- 总内存:$MEM_TOTAL MB- 已使用:$MEM_USED MB- 空闲内存:$MEM_FREE MB- 告警阈值:$MEM_THRESHOLD%3. 磁盘状态(/分区)- 当前使用率:$DISK_USAGE%- 总容量:$DISK_TOTAL- 已使用:$DISK_USED- 剩余空间:$DISK_FREE- 告警阈值:$DISK_THRESHOLD%4. IO状态- 当前await值:$IO_AWAIT_INT 毫秒- 告警阈值:$IO_THRESHOLD 毫秒5. 网络状态($INTERFACE)- 下载速率:$RX_RATE MB/s- 上传速率:$TX_RATE MB/s- 告警阈值:$NET_THRESHOLD MB/s=============================
告警内容:
${ALERT_MSG:-无告警信息,系统状态正常}=============================
系统自动发送,请勿回复。"# 记录监控日志
echo "[$CURRENT_TIME] 开始发送监控邮件" >> "$LOG_FILE"
echo "邮件内容:$BODY" >> "$LOG_FILE"# 静默发送邮件(移除-v参数,仅错误日志写入DEBUG_LOG)
echo -e "Subject: $SUBJECT\n\n$BODY" | msmtp -C /etc/msmtprc "$EMAIL" 2>> "$DEBUG_LOG"# 输出结果到终端(仅关键信息)
if [ $? -eq 0 ]; thenecho "[$CURRENT_TIME] ✅ 监控邮件发送成功"echo "[$CURRENT_TIME] 发送成功" >> "$LOG_FILE"
elseecho "[$CURRENT_TIME] ❌ 邮件发送失败,查看调试日志:$DEBUG_LOG"echo "[$CURRENT_TIME] 发送失败" >> "$LOG_FILE"
fi
2. 脚本关键部分解析
(1)配置区:灵活调整参数
所有可自定义的参数都集中在「核心配置区」,比如将NET_THRESHOLD
从10MB/s改为20MB/s,只需修改一个变量,无需改动逻辑代码。
(2)资源监控:避免命令依赖报错
- 监控IO时,先用
command -v iostat
判断工具是否安装,避免脚本因命令缺失崩溃; - 网络监控前,先检查网卡是否存在(
[ -d "/sys/class/net/$INTERFACE" ]
),减少异常场景。
(3)邮件发送:静默模式更友好
- 移除msmtp的
-v
参数,不显示邮件服务器交互过程; - 错误日志用
2>>
追加写入,仅当发送失败时才记录,避免日志冗余。
四、脚本使用与自动化部署
脚本编写完成后,需赋予执行权限并配置定时任务,实现「无人值守监控」。
1. 脚本执行与测试
# 赋予执行权限
chmod +x system_monitor.sh
# 手动执行脚本(测试是否正常运行)
./system_monitor.sh
执行后,终端会显示「发送成功/失败」,同时可查看/tmp/monitor_final.log
日志,确认监控数据是否正确。
2. 配置定时任务(crontab)
用crontab
设置定时执行,比如每5分钟监控一次:
# 编辑crontab任务
crontab -e
# 添加以下内容(每5分钟执行一次,日志输出到/dev/null避免邮件轰炸)
*/5 * * * * /path/to/system_monitor.sh > /dev/null 2>&1
*/5 * * * *
:表示每5分钟执行一次(时间格式:分 时 日 月 周);/path/to/system_monitor.sh
:替换为脚本的实际路径(如/root/demo3/system_monitor.sh
);> /dev/null 2>&1
:屏蔽脚本输出,避免crontab发送无关邮件。
五、常见问题排查
-
邮件发送失败?
查看/tmp/msmtp_debug.log
,常见原因:- 授权码错误:重新生成QQ邮箱授权码;
- 端口被封:将SMTP端口从25改为465(需开启
tls on
); - 服务器IP被拉黑:换用163邮箱(SMTP服务器
smtp.163.com
)。
-
磁盘使用率计算错误?
若df -h /
输出格式不同,可能导致awk
取错列。可先执行df -h /
查看输出,调整awk '{print $5}'
中的列数(比如改为$4
)。 -
网络速率显示为0?
检查网卡名是否正确(用ls /sys/class/net/
查看),或延长sleep
时间(比如从1秒改为5秒),避免短时间内流量变化过小。
六、脚本扩展建议
- 增加多磁盘监控:当前仅监控根分区(
/
),可添加DISK_PARTITIONS="/ /home /data"
,用循环遍历多个分区; - 支持多收件人:将
EMAIL
改为数组(EMAIL=("a@qq.com" "b@163.com")
),循环发送邮件; - 添加告警抑制:避免同一问题频繁告警(比如1小时内只告警1次),可通过日志判断上次告警时间。
通过这个脚本,我们实现了Linux系统的全维度监控,且配置简单、易于维护。无论是个人服务器还是企业运维,都能通过它及时发现资源异常,减少服务故障风险。如果有其他监控需求,也可以基于这个框架扩展,比如增加进程监控、端口存活检测等功能~