定时检查内存使用并告警脚本全面指南
目录导读
- 为什么要监控内存使用? - 内存泄漏与系统崩溃的隐形杀手
- 核心脚本实现 - 从零搭建内存监控告警系统
- 告警机制设计 - 邮件/钉钉/企业微信多渠道通知
- 定时任务配置 - crontab与systemd timer实战
- 常见问题与问答 - 解决脚本运行中的10个关键疑惑
为什么要监控内存使用?
在服务器运维中,内存是决定应用稳定性的核心资源,据Stack Overflow 2023年调查数据显示,超过34%的服务器故障与内存耗尽直接相关,当内存使用率超过90%时,系统会触发OOM Killer(内存溢出杀手),随机终止进程——这可能导致核心业务中断。

典型场景:
- Java应用内存泄漏(如堆内存不断增长)
- 缓存服务(Redis/Memcached)缓存膨胀
- 数据库查询未释放临时内存
- 容器化环境(Docker/K8s)内存限制不当
痛点:人工巡检效率低,且无法实时发现突增。
核心脚本实现:定时检查内存使用并告警脚本
以下脚本基于Bash编写,兼容CentOS 7+/Ubuntu 18.04+,支持自定义阈值:
#!/bin/bash
# 内存监控告警脚本 - memory-monitor.sh
# ===== 配置区域 =====
THRESHOLD=80 # 内存使用率告警阈值 (%)
ALERT_LOG="/var/log/memory-alert.log"
MAIL_TO="admin@example.com"
# ===== 获取内存使用率 =====
get_mem_usage() {
# 使用free命令获取内存信息
local total=$(free -m | awk '/^Mem:/ {print $2}')
local used=$(free -m | awk '/^Mem:/ {print $3}')
# 计算使用率(保留两位小数)
local usage=$(echo "scale=2; $used * 100 / $total" | bc)
# 输出纯数字(去掉小数)
echo "$usage" | cut -d. -f1
}
# ===== 核心监控逻辑 =====
mem_usage=$(get_mem_usage)
current_time=$(date "+%Y-%m-%d %H:%M:%S")
hostname=$(hostname)
# 判断是否超过阈值
if [ "$mem_usage" -ge "$THRESHOLD" ]; then
# 记录告警日志
echo "$current_time WARNING: Memory usage $mem_usage% (threshold: $THRESHOLD%)" >> "$ALERT_LOG"
# 获取占用内存前5的进程
top_processes=$(ps aux --sort=-%mem | head -6 | tail -5)
# 发送告警(支持邮件/Webhook/钉钉)
alert_message="⚠️ 服务器 [$hostname] 内存告警
时间:$current_time
内存使用率:$mem_usage%
阈值:$THRESHOLD%
Top 5 内存进程:
$top_processes"
# 邮件告警(需要配置mail命令)
echo "$alert_message" | mail -s "[ALERT] Server $hostname Memory Usage $mem_usage%" "$MAIL_TO"
# 可选:钉钉机器人(Webhook)
# curl -X POST -H "Content-Type: application/json" -d '{"msgtype":"text","text":{"content":"'"$alert_message"'"}}' "https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN"
fi
exit 0
脚本说明:
- 灵活配置:调整
THRESHOLD变量即可改变告警阈值 - 进程分析:自动输出消耗内存最多的5个进程,帮助定位问题
- 日志持久化:所有告警记录到
/var/log/memory-alert.log,便于事后审计
告警机制设计
脚本内置了邮件告警,但实际生产环境需要更丰富的方式:
| 告警方式 | 实现方法 | 优势 |
|---|---|---|
| 邮件 | 使用mail命令 |
标准、易集成 |
| 钉钉/飞书 | Webhook POST请求 | 即时通知、支持卡片消息 |
| 企业微信 | 机器人API | 与办公协同无缝衔接 |
| PagerDuty | API调用 | 适合大企业值班体系 |
进阶方案:集成Prometheus + Grafana后,可通过Alertmanager实现告警路由与分组。
定时任务配置
方案A:crontab(推荐)
# 每5分钟执行一次监控 */5 * * * * /opt/scripts/memory-monitor.sh
方案B:systemd timer(更稳定)
创建服务文件:
# /etc/systemd/system/memory-monitor.service [Service] ExecStart=/opt/scripts/memory-monitor.sh # /etc/systemd/system/memory-monitor.timer [Timer] OnCalendar=*:0/5 # 每5分钟 Persistent=true
启用:
systemctl daemon-reload systemctl enable --now memory-monitor.timer
常见问题与问答
Q1:脚本中如何精确获取内存使用率?
A:使用free -m获取MB单位数据,通过awk提取total和used字段,再经bc计算百分比,注意echo管道传递给bc时需使用scale控制小数精度。
Q2:为什么告警阈值设为80%而非95%? A:80%是缓冲阈值,内存达到80%时,操作系统会开始使用swap(如果开启),同时OOM Killer的触发风险在90%以上飙升,留出20%缓冲可避免误告警。
Q3:如何区分内存泄漏和正常业务高峰?
A:需结合趋势分析,可在脚本中加入历史记录功能(如用rrdtool或文件记录每5分钟的内存值),当内存持续增长而非波动时,才触发二次告警。
Q4:容器环境(Docker)如何监控?
A:在容器内使用cat /sys/fs/cgroup/memory/memory.usage_in_bytes获取容器分配内存使用量,配合memory.limit_in_bytes计算使用率,但建议在宿主机层面通过cAdvisor或Prometheus node_exporter统一采集。
Q5:告警太多如何抑制?
A:实现告警去重机制:脚本中记录上次告警时间,如果距离上次告警时间小于30分钟,则跳过邮件发送,仅追加日志,或集成Alertmanager中的inhibit_rules。
Q6:脚本执行权限与路径问题?
A:将脚本放置于/opt/scripts目录,确保chmod +x执行权限,crontab中使用绝对路径以避免环境变量问题。
Q7:如何实现Swap监控?
A:增加Swap使用率检查:free -m | awk '/^Swap/ {if($2>0) print $3*100/$2}',当Swap使用率>50%且内存>80%时,触发严重告警。
Q8:生产环境下脚本需要加锁防止并发吗?
A:是的,使用flock或mkdir锁机制,因为crontab间隔可能因系统繁忙导致重叠执行,锁可防止多个实例同时运行。
Q9:如何测试脚本正确性?
A:最小化测试环境:在测试服务器上设置THRESHOLD=1,触发告警并检查日志和邮件/钉钉是否收到,也可配合stress命令手动占用内存:stress --vm 2 --vm-bytes 1G --timeout 60。
Q10:脚本是否支持ARM架构(树莓派)?
A:支持。free命令在所有Linux发行版上一致,bc计算也跨平台,注意树莓派内存较小,建议将阈值调整为70%。
通过本文的定时检查内存使用并告警脚本,你可以用5分钟快速部署一套可靠的内存监控系统,它不仅能在内存膨胀时第一时间推送通知,更能通过输出top进程帮助快速定位原因,结合crontab定时任务,实现7×24小时无人值守运维——这正是现代DevOps工程师必备的生产力工具,立即在你的服务器上运行这个脚本,让内存泄漏无处遁形。