作为一个站长或者服务器运维,最怕的就是服务器突然宕机或者资源耗尽,而你却毫不知情。等到用户反馈或者网站打不开时才去处理,往往已经造成了损失。有没有一种简单有效的方法,能够实时监控服务器状态,并在出现问题时及时通知你呢?今天,我就和大家分享一个自己写的服务器监控脚本,用Bash实现,功能包括每分钟记录CPU负载、内存使用、磁盘空间,超出阈值时发送告警。代码完整可运行,注释详细,你可以直接拿去用。
为什么需要监控脚本?
虽然有很多成熟的监控系统如Zabbix、Prometheus、Nagios等,但对于个人站长或者小型团队来说,部署和维护这些系统可能过于复杂。有时候我们只需要一个轻量级的脚本,能快速部署,灵活定制告警规则。而且自己写脚本还可以加深对系统资源的理解,何乐而不为呢?我自己就曾因为磁盘写满导致服务中断,从那以后就养成了写监控脚本的习惯。这个脚本陪我度过了很多个安稳的夜晚,今天分享出来,希望能帮到同样在折腾服务器的你。
设计思路
这个脚本的核心思路很简单:读取系统文件或命令的输出,获取CPU负载、内存使用率和磁盘使用率,然后与预设的阈值比较。如果超过阈值,就发送告警。同时,为了保留历史数据,我们会将每次的监控结果记录到日志文件中。
具体来说:
- CPU负载:使用
/proc/loadavg文件获取1分钟、5分钟、15分钟的平均负载。 - 内存使用:使用
free命令获取总内存、已用内存、可用内存。 - 磁盘空间:使用
df命令获取指定分区的使用率。 - 告警方式:通过
mail命令发送邮件,或者通过curl调用Webhook(如钉钉、企业微信),你可以在配置区域自由切换。 - 日志记录:将每次检查结果追加到日志文件,方便回溯。
脚本采用函数式结构,配置与逻辑分离,你只需要修改开头的几个变量就能适配自己的环境。
Bash脚本实现
下面就是完整的脚本代码,我已经加上了详细的注释,你可以直接复制保存为 monitor.sh,然后赋予执行权限即可运行。
#!/bin/bash
# ============================================================
# 服务器监控脚本
# 功能:监控CPU负载、内存使用、磁盘空间,超阈值告警
# 作者:技术小能手
# 版本:1.0
# ============================================================
# ---------- 配置区域(根据你的需求修改) ----------
# 告警阈值
CPU_LOAD_THRESHOLD=2.0 # CPU 1分钟平均负载阈值(根据核心数调整,一般设为核心数的70%)
MEM_USAGE_THRESHOLD=80 # 内存使用率百分比阈值
DISK_USAGE_THRESHOLD=90 # 磁盘使用率百分比阈值(针对根分区)
# 监控的磁盘分区(可以多个,用空格分隔)
DISK_PARTITIONS="/ /data"
# 日志文件路径
LOG_FILE="/var/log/server_monitor.log"
# 告警方式:可选 "mail" 或 "webhook"
ALERT_METHOD="mail"
# 邮件告警配置(当 ALERT_METHOD="mail" 时有效)
MAIL_TO="admin@example.com"
MAIL_SUBJECT_PREFIX="[服务器告警]"
# Webhook 配置(当 ALERT_METHOD="webhook" 时有效)
WEBHOOK_URL="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY"
# ---------- 配置结束 ----------
# ---------- 函数定义 ----------
# 获取当前时间戳
get_timestamp() {
date "+%Y-%m-%d %H:%M:%S"
}
# 记录日志
log_message() {
local msg="$1"
echo "$(get_timestamp) - $msg" >> "$LOG_FILE"
}
# 发送告警
send_alert() {
local subject="$MAIL_SUBJECT_PREFIX $1"
local body="$2"
if [ "$ALERT_METHOD" = "mail" ]; then
echo "$body" | mail -s "$subject" "$MAIL_TO"
log_message "邮件告警已发送: $subject"
elif [ "$ALERT_METHOD" = "webhook" ]; then
curl -s -X POST "$WEBHOOK_URL" -H "Content-Type: application/json" -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$subject\n$body\"}}" > /dev/null
log_message "Webhook告警已发送: $subject"
else
log_message "未知的告警方式: $ALERT_METHOD"
fi
}
# ---------- 监控逻辑 ----------
main() {
log_message "===== 开始监控 ====="
# 1. CPU负载
# 从 /proc/loadavg 读取1分钟、5分钟、15分钟负载
loadavg=$(cat /proc/loadavg)
load1=$(echo "$loadavg" | awk '{print $1}')
load5=$(echo "$loadavg" | awk '{print $2}')
load15=$(echo "$loadavg" | awk '{print $3}')
log_message "CPU负载: 1min=$load1, 5min=$load5, 15min=$load15"
# 检查是否超过阈值(使用浮点数比较)
if (( $(echo "$load1 > $CPU_LOAD_THRESHOLD" | bc -l) )); then
send_alert "CPU负载过高" "当前1分钟负载: $load1 (阈值: $CPU_LOAD_THRESHOLD)"
fi
# 2. 内存使用
# 使用 free 命令,提取已用和总计,计算使用率
mem_info=$(free -m | grep "^Mem:")
total_mem=$(echo "$mem_info" | awk '{print $2}')
used_mem=$(echo "$mem_info" | awk '{print $3}')
mem_usage=$(echo "scale=2; $used_mem * 100 / $total_mem" | bc)
log_message "内存使用: ${used_mem}MB / ${total_mem}MB (${mem_usage}%)"
if (( $(echo "$mem_usage > $MEM_USAGE_THRESHOLD" | bc -l) )); then
send_alert "内存使用过高" "当前内存使用率: ${mem_usage}% (阈值: ${MEM_USAGE_THRESHOLD}%)"
fi
# 3. 磁盘空间
for partition in $DISK_PARTITIONS; do
# 使用 df 获取指定分区的使用率,忽略标题行
disk_info=$(df -h "$partition" | tail -1)
disk_usage=$(echo "$disk_info" | awk '{print $5}' | sed 's/%//')
disk_total=$(echo "$disk_info" | awk '{print $2}')
disk_used=$(echo "$disk_info" | awk '{print $3}')
disk_avail=$(echo "$disk_info" | awk '{print $4}')
log_message "磁盘 $partition: 总大小 $disk_total, 已用 $disk_used, 可用 $disk_avail, 使用率 ${disk_usage}%"
if [ "$disk_usage" -gt "$DISK_USAGE_THRESHOLD" ]; then
send_alert "磁盘空间不足 ($partition)" "当前使用率: ${disk_usage}% (阈值: ${DISK_USAGE_THRESHOLD}%)"
fi
done
log_message "===== 监控结束 ====="
}
# 执行主函数
main使用方法:
- 将脚本保存为
monitor.sh,并根据你的环境修改配置区域的参数(阈值、日志路径、告警方式等)。 - 赋予执行权限:
chmod +x monitor.sh - 如果你想每分钟运行一次,可以配置cron任务:
crontab -e,添加一行* * * * * /path/to/monitor.sh - 或者直接运行
./monitor.sh测试效果。
脚本详解
我来简单解释一下脚本的关键部分:
- 配置区域:你可以轻松调整阈值、日志路径、告警方式。告警方式支持邮件和Webhook,个人用邮件很方便,团队用Webhook可以集成到钉钉、企业微信等协作工具。我一般在家用邮件,在公司用Webhook,一个脚本两种选择。
- 日志记录:每次检查都会记录到日志文件,方便你回顾历史状态。如果你愿意,还可以把日志导入到ELK或Grafana,实现可视化。
- 告警函数:当某个指标超过阈值时,会调用
send_alert函数,根据配置发送告警。告警内容包含当前值和阈值,让你一目了然。 - CPU负载:通过
/proc/loadavg读取,这是最直接的方式。负载阈值建议根据CPU核心数设定,一般不超过核心数的70%。比如4核CPU,阈值设为2.8比较合理。 - 内存使用率:通过
free -m计算,这里包含了缓存和缓冲区。如果你希望监控“真实”使用率,可以减去buff/cache部分,脚本中留了接口,你可以自行修改。 - 磁盘空间:使用
df -h,我手动指定了分区列表,避免监控无关的虚拟文件系统。你可以根据需要添加更多分区,比如/var、/home等。
我个人更喜欢Bash实现,因为它无需任何额外依赖,任何Linux服务器都能直接运行。如果你对Python更熟悉,也可以用Python重写,利用 psutil 库会更简洁,但需要提前安装依赖。
如何设置定时任务
脚本本身只执行一次监控,要让它每分钟自动运行,需要借助cron。在终端输入 crontab -e,添加以下内容:
* * * * * /path/to/monitor.sh保存后cron就会自动每分钟执行一次。如果你希望脚本自己循环运行(比如作为守护进程),可以在 main 外面加一个 while true; do main; sleep 60; done,但我更推荐cron方式,因为它的日志和进程管理更清晰。
扩展与优化
这个脚本虽然简单,但已经具备了一个监控工具的基本要素。你可以基于它进行扩展:
- 增加网络流量监控(使用
/proc/net/dev或sar)。 - 增加进程监控(检查某个关键进程是否存活)。
- 将日志存储到数据库或发送到远程日志系统。
- 使用Python重写,可以更方便地处理数据和发送告警(比如通过SMTP库、requests库)。
另外,如果你不想自己维护服务器,也可以考虑使用云服务商的监控产品。比如 雨云服务器 就提供了内置的监控和告警功能,开箱即用,省去自己搭建的麻烦。而且现在通过优惠码 aabh 还能享受折扣,性价比很高。对于不想折腾的朋友,直接上云服务可能是更省心的选择。
总结
自己写一个监控脚本并不难,它不仅能帮你及时发现问题,还能让你更深入了解服务器的运行状态。本文提供的Bash脚本简单实用,你可以直接部署。当然,生产环境还是建议使用成熟的监控系统,但对于个人项目或临时需求,这个脚本完全够用。我到现在还在用这个脚本监控我的几台小服务器,每天看一眼日志,心里特别踏实。
如果你有任何问题或改进建议,欢迎在评论区交流。如果你觉得这篇分享有帮助,不妨点个赞或分享给需要的朋友。下次再见!
评论区: