别再让服务器因磁盘爆满宕机!一个脚本实时监控+告警

前言

在运维工作中,没有什么比深夜收到“服务器宕机”告警更令人心悸的了——而罪魁祸首,往往只是磁盘空间悄无声息地耗尽。日志不断堆积、临时文件无人清理、备份任务失控……这些看似微小的疏忽,足以让关键服务瞬间瘫痪,影响业务、损失数据,甚至打乱整个团队的节奏。

别再被动“救火”!本文将分享一个轻量级但高效的Shell脚本方案,可实时监控Linux服务器磁盘使用率,并在阈值超标时第一时间通过微信/邮件/钉钉发出告警。部署只需几分钟,却能为你筑起一道可靠的存储防线,让系统稳定运行,告别“磁盘爆满式宕机”。

downloaded-image (1)

1.为什么配置磁盘监控+告警?

磁盘爆满 = 服务瘫痪

当磁盘使用率达到100%时:

  • 新日志无法写入 → 应用崩溃或静默失败
  • 数据库无法写事务 → MySQL/PostgreSQL直接挂起或报错
  • 临时文件无法创建 → Web服务(如Nginx、PHP)返回500错误
  • 系统进程异常 → systemd、cron等核心功能可能失效

问题往往“悄无声息”发生

  • 日志每天增长几百MB,短期内无感,但几周后突然爆满
  • 自动备份脚本未清理旧文件,存储被历史备份占满
  • 容器/虚拟机镜像、缓存文件持续累积,无人关注直到宕机

人类无法24小时盯屏,但脚本能。

提前告警 = 主动运维

  • 在磁盘使用率达80%~90%时发出预警,留出充足时间处理
  • 可自动触发清理脚本(如logrotate、删除旧备份)
  • 避免深夜被“服务器宕机”电话惊醒

成本极低,收益极高

  • 一个10行Shell脚本 + 免费告警通道(如Server酱、企业微信)即可实现
  • 无需额外监控系统(如Zabbix、Prometheus),适合个人、家庭 NAS、小型业务
  • 一次配置,长期守护

满足合规与可靠性要求

  • 对于有SLA(服务等级协议)的业务,可用性是硬指标
  • 磁盘空间监控是IT运维基线检查项(如等保、ISO 27001)

总结一句话

不监控磁盘,等于把系统稳定性交给运气。而一个简单的告警脚本,就是你对抗“意外宕机”最经济、最有效的武器。

2.获取钉钉Webhook URL

打开钉钉群 → 点击右上角设置:

image-20260325141357694

找到智能群助手 → 添加机器人:

image-20260325141635253

image-20260325141712706

添加自定义机器人:

image-20260325141746662

点击添加:

image-20260325141818703

给机器人起个名字,我这里是“磁盘告警”:

image-20260402110254731

设置发消息关键词,因为现在钉钉对安全严格,所以需要设置限制,,也可以设置加签或者IP地址:

image-20260325143147879

点击完成后,复制生成的Webhook,留着备用:

image-20260325143249017

3.创建监控脚本实现钉钉告警

3.1 编写监控脚本

磁盘使用率监控 + 钉钉告警脚本。当任意分区使用率超过 20%(可以自己设置对应值,我这是为了更好展示),即向钉钉群机器人发送通知。

创建一个专属于监控的目录,并进入到这个目录下:

mkdir -p jiankong
cd jiankong

1566f661c7cabe435b240f6804501bfd

编写钉钉告警及监控磁盘使用情况的告警:

 vi disk_monitor.sh
 chmod +x  disk_monitor.sh
#!/bin/bash

# =============== 配置区 ===============
DINGTALK_WEBHOOK="https://oapi.dingtalk.com/robot/send?access_token=a39180a7b3c3********3601f8d59faa"
THRESHOLD=20
HOSTNAME=$(hostname)

# 临时文件存储告警信息
ALERT_MSG=""

# 获取磁盘使用情况(避免子shell,直接在主shell处理)
df -h -t ext4 -t xfs -t btrfs -t ext3 -t ext2 2>/dev/null | awk 'NR>1 {print $5 " " $1 " " $6}' | while read usage filesystem mountpoint; do
    use_pct=$(echo "$usage" | tr -d '%')
    if [ "$use_pct" -gt "$THRESHOLD" ]; then
        # 将告警信息追加到变量(但由于管道会创建子shell,此方法仍可能失效)
        echo "⚠ 分区: $filesystem ($mountpoint) 使用率: ${use_pct}%"
    fi
done > /tmp/disk_alerts.txt

# 改为:在主 shell 中读取 df 输出(推荐方式)
ALERT_MSG=""
while IFS= read -r line; do
    usage=$(echo "$line" | awk '{print $1}')
    filesystem=$(echo "$line" | awk '{print $2}')
    mountpoint=$(echo "$line" | awk '{print $3}')
    use_pct=$(echo "$usage" | tr -d '%')
    if [ "$use_pct" -gt "$THRESHOLD" ]; then
        ALERT_MSG+="- 分区: $filesystem\n  挂载点: $mountpoint\n  使用率: ${use_pct}%\n\n"
    fi
done < <(df -h -t ext4 -t xfs -t btrfs -t ext3 -t ext2 2>/dev/null | awk 'NR>1 {print $5 " " $1 " " $6}')

# 如果有告警内容,则发送
if [ -n "$ALERT_MSG" ]; then
    # 构建完整消息(使用 printf 处理换行)
    FULL_MSG="磁盘使用率告警
主机: $HOSTNAME
阈值: ${THRESHOLD}%

$ALERT_MSG"

    # 发送钉钉消息(text 类型支持换行)
    curl -s -X POST "$DINGTALK_WEBHOOK" \
         -H 'Content-Type: application/json' \
         -d "{
               \"msgtype\": \"text\",
               \"text\": {
                   \"content\": \"$FULL_MSG\"
               }
             }" >/dev/null
fi

# 清理临时数据(如有)
rm -f /tmp/disk_alerts.txt 2>/dev/null

65de4d04d6e70231afd0b8e4bb9c67b0

添加成功后,执行这个脚本:

bash disk_monitor.sh

image-20260402144251142

执行成功后,我们可以在钉钉群中查看告警,发现告警成功:

7bb2755285bd7ffa1d8e1c74b1d3adad

3.2 遇到的问题

发现钉钉未收到告警,测试是否可以连通网络:

curl -v https://oapi.dingtalk.com

DNS解析失败:你的服务器无法将域名oapi.dingtalk.com转换为IP地址。

常见原因:

  • 没有配置 DNS 服务器(如 /etc/resolv.conf 为空或无效)
  • 网络未正确设置默认网关,导致无法访问外网 DNS(如 8.8.8.8 或 114.114.114.114)
  • 虚拟机 NAT/桥接配置错误(常见于 VMware/VirtualBox)

此时即使有公网 IP,也无法通过域名访问任何网站。

我们先手动添加默认路由:

ip route add default via 192.168.42.2 dev ens33

最后在测试,发现可以连通了:

curl -v https://oapi.dingtalk.com

08885159314ef21903afda9f9cd7d573

4.设置定时任务

设置定时任务(每5分钟检查一次),编辑 crontab:

crontab -e

添加一行:

*/5 * * * * /root/jiankong/disk_monitor.sh >/dev/null 2>&1

image-20260402145129933

image-20260402145307952

接下来,它每隔5分钟就会执行一遍这个脚本啦!

钉钉每隔5分钟就会发生告警!

5.构建告警可视化页面

如果你不想依赖钉钉,或者想有一个可视化页面,可以:

5.1 写一个简单的Web服务(用Python快速搭建)

创建目录:

mkdir -p /opt/disk-monitor && cd /opt/disk-monitor
vi generate_html.sh
cat > generate_html.sh << 'EOF'
#!/bin/bash
cat << HTML > index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>磁盘监控</title>
  <style>body { font-family: Arial; padding: 20px; }</style>
</head>
<body>
  <h2>📊 磁盘使用情况($(date))</h2>
  <pre>$(df -h)</pre>
  <h3>⚠ 高使用率分区:</h3>
  <pre>$(df -h | awk 'NR>1 { gsub(/%/,"",$5); if($5+0 > 80) print $0 }')</pre>
</body>
</html>
HTML
EOF

添加执行权限:

chmod +x generate_html.sh

cd44610e3fe6c640afa508b0e6c339af

启动一个简易HTTP服务器:

# 安装 Python(如未安装)
yum install -y python3  # CentOS
apt install -y python3 # Ubuntu

启动Web服务(端口 3060):

cd /opt/disk-monitor
nohup python3 -m http.server 3060 > web.log 2>&1 &

fe44f25fb9da61824030f6f4d81b4330

5.2 创建index.html文件

写一个index.html文件,为了3060端口网页更加美观直接:

创建df.txt并写入磁盘信息:

# 进入你的Web目录(比如 /opt/disk-monitor)
cd /opt/disk-monitor

# 手动创建测试文件
df -h > df.txt

# 查看是否成功
cat df.txt

ab0c7c53e8b881d98319c1be61e16851

在你的Web服务根目录(比如/opt/disk-monitor)下创建一个index.html:

cd /opt/disk-monitor
cat > index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>磁盘监控面板</title>
  <style>
    body { font-family: Arial; padding: 20px; background: #f5f5f5; }
    .container { max-width: 800px; margin: auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
    h1 { color: #333; }
    pre { background: #eee; padding: 10px; overflow-x: auto; }
    .alert { color: red; font-weight: bold; }
  </style>
</head>
<body>
  <div class="container">
    <h1>📊 磁盘监控</h1>
    <p><strong>更新时间:</strong> <span id="time"></span></p>

    <h2>磁盘使用情况</h2>
    <pre id="df-output"></pre>

    <h2>⚠ 高使用率分区(>20%)</h2>
    <pre id="high-usage"></pre>
  </div>

  <script>
    function updateData() {
      fetch('/df.txt')
        .then(res => res.text())
        .then(data => {
          document.getElementById('df-output').textContent = data;
          // 提取高使用率分区
          const high = data.split('\n').filter(line => line.includes('%') && line.match(/(\d+)%/)).map(line => {
            const match = line.match(/(\d+)%/);
            if (match && parseInt(match[1]) > 20) return line;
            return '';
          }).filter(Boolean).join('\n');
          document.getElementById('high-usage').textContent = high || '无';
        });

      document.getElementById('time').textContent = new Date().toLocaleString();
    }

    updateData();
    setInterval(updateData, 30000); // 每30秒刷新一次
  </script>
</body>
</html>
EOF

c8f91d53f2a677d81202fce5130477c3

使用python构建成功后,在浏览器中输入 http://IP:3060 就能看到告警可视化的界面:

b20b8597eb2f0029a97e56263beea638

划到下面,可以看见大于20%的告警:

e597cb02a317d41c31085b174c39bff2

当你在家、不在公司内网环境时,想查看部署在内网的可视化告警界面,而这些服务又没有公网IP,这时候cpolar就能派上大用场。用cpolar把你家里的电脑或公司内网的服务“穿”到公网上,让你随时随地通过一个网址访问它。

跟我一起来部署cpolar吧!

6.安装cpolar实现随时随地开发

你是否遇到过这样的问题?

我在本地或内网部署了强大的 哪吒监控面板(Nezha Monitor),能实时查看服务器状态、网络流量、CPU负载……

但一旦离开公司/家庭网络,就再也无法访问?

想远程排查故障,却只能干着急?

传统方案如公网IP、DDNS、FRP、Nginx反向代理等,要么成本高,要么配置复杂,还涉及端口暴露、安全策略、动态IP等麻烦。

是时候认识 cpolar了!

cpolar—— 新一代内网穿透工具,专为开发者与运维打造。

6.1 什么是cpolar?

cpolar是一款安全高效的内网穿透工具,无需公网IP或复杂配置,只需一条命令,即可将本地服务器、Web服务或任意端口映射到公网,让你随时随地远程访问内网应用,特别适合开发调试、远程运维和应急部署等场景。

6.2 部署cpolar

cpolar 可以将你本地电脑中的服务(如 SSH、Web、数据库)映射到公网。即使你在家里或外出时,也可以通过公网地址连接回本地运行的开发环境。

❤️以下是安装cpolar步骤:

官网在此:https://www.cpolar.com

使用一键脚本安装命令:

sudo curl https://get.cpolar.sh | sh

image-20250725104019896

安装完成后,执行下方命令查看cpolar服务状态:(如图所示即为正常启动)

sudo systemctl status cpolar

22e5adfaf290a17fc3384bb296055259

Cpolar安装和成功启动服务后,在浏览器上输入虚拟机主机IP加9200端口即:【http://ip:9200】访问Cpolar管理界面,使用Cpolar官网注册的账号登录,登录后即可看到cpolar web 配置界面,接下来在web 界面配置即可:

打开浏览器访问本地9200端口,使用cpolar账户密码登录即可,登录后即可对隧道进行管理。

8a6698b1bf26d64ba3645827fbfb1c29

7.配置公网地址

登录cpolar web UI管理界面后,点击左侧仪表盘的隧道管理——创建隧道:

  • 隧道名称:可自定义,本例使用了:,注意不要与已有的隧道名称重复
  • 协议:http
  • 本地地址:3060
  • 域名类型:随机域名
  • 地区:选择China Top

image-20260402171431475

创建成功后,打开左侧在线隧道列表,可以看到刚刚通过创建隧道生成了公网地址,接下来就可以在其他电脑或者移动端设备(异地)上,使用地址访问。

image-20260402171512442

访问成功。

image-20260402172829156

8.保留固定公网地址

使用cpolar为其配置二级子域名(cpolar官网-安全的内网穿透工具 | 无需公网ip | 远程访问 | 搭建网站),该地址为固定地址,不会随机变化。

image-20250918151358733

点击左侧的预留,选择保留二级子域名,地区选择china Top,然后设置一个二级子域名名称,我使用的是surveillance,大家可以自定义。填写备注信息,点击保留。

image-20260402172946557

登录cpolar web UI管理界面,点击左侧仪表盘的隧道管理——隧道列表,找到所要配置的隧道,点击右侧的编辑

image-20260402173025916

修改隧道信息,将保留成功的二级子域名配置到隧道中

  • 域名类型:选择二级子域名
  • Sub Domain:填写保留成功的二级子域名
  • 地区: China Top

点击更新

image-20260402173111888

更新完成后,打开在线隧道列表,此时可以看到随机的公网地址已经发生变化,地址名称也变成了保留和固定的二级子域名名称。

image-20260402173138676

最后,我们使用固定的公网地址在任意设备的浏览器中访问,可以看到成功访问的页面,这样一个永久不会变化的二级子域名公网网址即设置好了。

image-20260402173208368

总结

服务器因磁盘爆满而宕机,往往是“小疏忽酿大祸”。其实只需一个轻量级Shell脚本,配合crontab定时任务,就能实时监控磁盘使用率,并在超过阈值(如90%)时自动通过邮件、钉钉或企业微信等渠道告警,5分钟部署,零成本预防故障,真正做到“防患于未然”,告别深夜救火式运维。

感谢您对本篇文章的喜爱,有任何问题欢迎留言交流。cpolar官网-安全的内网穿透工具 | 无需公网ip | 远程访问 | 搭建网站

Share:

发表回复

目录

On Key

推荐文章