menu E4b9a6's blog
rss_feed
E4b9a6's blog
有善始者实繁,能克终者盖寡。

Linux监控内存发送警告邮件

作者:E4b9a6, 创建:2024-08-21, 字数:2580, 已阅:250, 最后更新:2024-08-21

我有一台 1G4C 的迷你主机,容易内存超过极限负载导致宕机,为此写了一个 Bash 脚本来实现当内存使用率超过 80% 时发邮件提醒

脚本如下:

Bash
#!/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个软件:

Bash
# stress 可以模拟内存负载
sudo apt install supervisor stress

编辑: /etc/supervisor/conf.d/monitor-memory.conf

INI
[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

启动程序

Bash
sudo supervisorctl update

autorestart 设置为 false,这样脚本在发送通知邮件之后即不会再次运行

使用 stress 模拟内存占用来检验是否会发送邮件:

Bash
# 开启一条 400Mb 的内存占用线程,10秒后退出
stress --vm 1 --vm-bytes 400M --timeout 10

观察是否收到邮件通知,确认没问题后再次启动脚本:

Bash
sudo supervisorctl start monitor-memory

[[replyMessage== null?"发表评论":"发表评论 @ " + replyMessage.m_author]]

account_circle
email
web_asset
textsms

评论列表([[messageResponse.total]])

还没有可以显示的留言...
gravatar
[[messageItem.m_author]] [[messageItem.m_author]]
[[messageItem.create_time]]
[[getEnviron(messageItem.m_environ)]]
[[subMessage.m_author]] [[subMessage.m_author]] @ [[subMessage.parent_message.m_author]] [[subMessage.parent_message.m_author]]
[[subMessage.create_time]]
[[getEnviron(messageItem.m_environ)]]