作者:E4b9a6, 创建:2024-08-21, 字数:2580, 已阅:250, 最后更新:2024-08-21
我有一台 1G4C 的迷你主机,容易内存超过极限负载导致宕机,为此写了一个 Bash 脚本来实现当内存使用率超过 80% 时发邮件提醒
脚本如下:
#!/bin/bash
SUBJECT="Memory Warning"
TO="my_email@google.com"
SMTP_SERVER="smtp://smtp.server.com"
USERNAME="username"
PASSWORD="password"
# 监控内存使用率的函数
check_memory() {
MEM_USAGE=$(free | grep Mem | awk '{print $3/$2 * 100.0}')
MEM_USAGE=${MEM_USAGE%.*} # 转换为整数
echo "$MEM_USAGE"
}
# 监控磁盘使用率的函数
check_disk_usage() {
DISK_USAGE=$(df / | grep / | awk '{ print $5 }' | sed 's/%//g')
echo "$DISK_USAGE"
}
# 监控负载的函数
check_load_average() {
LOAD_AVG=$(cat /proc/loadavg | awk '{print $1}')
LOAD_AVG=${LOAD_AVG%.*} # 转换为整数
echo "$LOAD_AVG"
}
# 发送邮件的函数
send_alert_email() {
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
BODY="警告:当前系统状态如下:
时间: $TIMESTAMP
内存使用率: $MEM_USAGE%
磁盘使用率: $DISK_USAGE%
最近负载: $LOAD_AVG%
当前系统状态(top 命令输出):
$(top -b -n 1 | head -n 40)" # 获取 top 命令的前40行
echo -e "From: $USERNAME\nTo: $TO\nSubject: $SUBJECT\n\n$BODY" | \
curl --url "$SMTP_SERVER" \
--ssl-reqd \
--mail-from "$USERNAME" \
--mail-rcpt "$TO" \
--upload-file - \
--user "$USERNAME:$PASSWORD"
}
# 主循环
while true; do
MEM_USAGE=$(check_memory)
DISK_USAGE=$(check_disk_usage)
LOAD_AVG=$(check_load_average)
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
echo "$TIMESTAMP 当前内存使用率: $MEM_USAGE%,当前磁盘使用率: $DISK_USAGE%,当前负载: $LOAD_AVG"
# 检查内存使用率
if [ "$MEM_USAGE" -gt 80 ]; then
echo "内存使用率超过 80%,发送警报邮件..."
send_alert_email
exit 1
fi
# 检查磁盘使用率
if [ "$DISK_USAGE" -gt 80 ]; then
echo "磁盘使用率超过 80%,发送警报邮件..."
send_alert_email
exit 1
fi
# 检查负载
if [ "$LOAD_AVG" -gt 8 ]; then
echo "负载超过 8,发送警报邮件..."
send_alert_email
exit 1
fi
sleep 30
done
脚本借助 curl
实现发送邮件,在检测到内存超过80%后发送邮件然后退出脚本
为了避免重复发邮件,将不采用 crontab 来定制执行,换成 supervisor 来运行程序,安装运行所需的2个软件:
# stress 可以模拟内存负载
sudo apt install supervisor stress
编辑: /etc/supervisor/conf.d/monitor-memory.conf
[program:monitor-memory]
command=/bin/bash /root/monitor-memory.sh
autostart=true
autorestart=false
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stdout_logfile_maxbytes=8MB
stdout_logfile_backups=1
redirect_stderr=true
user=root
启动程序
sudo supervisorctl update
将 autorestart
设置为 false
,这样脚本在发送通知邮件之后即不会再次运行
使用 stress
模拟内存占用来检验是否会发送邮件:
# 开启一条 400Mb 的内存占用线程,10秒后退出
stress --vm 1 --vm-bytes 400M --timeout 10
观察是否收到邮件通知,确认没问题后再次启动脚本:
sudo supervisorctl start monitor-memory