Shell 脚本 / 命令文档

Shell编程实战教学

$ disk 15 个章节 Linux 命令详解

概述

磁盘使用率监控报警脚本的设计与实现

需求分析

我们需要开发一个监控脚本,实现以下功能:

每分钟检测一次磁盘使用率

当使用率超过 80% 时开始记录

持续超标 5分钟 及以上触发报警

报警方式:记录日志、发送通知

使用率恢复正常后重置计数器

执行流程图

获取当前磁盘使用率(使用 df 命令)

判断使用率是否超过阈值(80%)

如果超过:累加计数器;如果未超过:重置计数器

检查计数器是否达到5(即5分钟)

达到条件则触发报警,记录日志并发送通知

等待60秒后循环执行

1. 获取磁盘使用率

Shell
                    # 方法一:使用 df 和 awk
usage=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')

# 方法二:指定文件系统
usage=$(df -h /dev/sda1 | tail -1 | awk '{print $5}' | tr -d '%')

# 解释:
# df -h /    : 查看根分区,-h 表示人类可读格式
# tail -1    : 获取最后一行(数据行)
# awk '{print $5}' : 提取第5列(使用率)
# sed 's/%//' : 去除百分号

2. 持久化计数器

由于脚本每次运行都是新进程,我们需要将计数器保存到文件中:

Shell
                    # 定义计数器文件路径
COUNTER_FILE="/tmp/disk_alert_counter.txt"

# 读取计数器(如果文件不存在则初始化为0)
if [[ -f $COUNTER_FILE ]]; then
    counter=$(cat $COUNTER_FILE)
else
    counter=0
fi

# 更新计数器
echo $counter > $COUNTER_FILE

3. 条件判断与计数逻辑

Shell
                    # 阈值设定
THRESHOLD=80
ALERT_MINUTES=5

if [[ $usage -gt $THRESHOLD ]]; then
    # 超过阈值,计数器加1
    counter=$((counter + 1))
    echo "警告: 磁盘使用率 ${usage}% 超过阈值,已持续 ${counter} 分钟"
    
    # 检查是否达到报警条件
    if [[ $counter -ge $ALERT_MINUTES ]]; then
        # 触发报警
        send_alert
    fi
else
    # 使用率正常,重置计数器
    counter=0
    echo "正常: 磁盘使用率 ${usage}%"
fi

完整实现脚本

disk_monitor.sh
                    #!/bin/bash

#======================================
# 磁盘使用率监控报警脚本
# 作者: Linux专家
# 功能: 监控磁盘使用率,持续超标5分钟后报警
#======================================

# 配置参数
THRESHOLD=80              # 使用率阈值(百分比)
ALERT_MINUTES=5          # 持续超标分钟数
CHECK_PARTITION="/"       # 要监控的分区
COUNTER_FILE="/tmp/disk_alert_counter.txt"
LOG_FILE="/var/log/disk_monitor.log"
ALERT_FLAG_FILE="/tmp/disk_alert_sent.flag"

# 日志函数
log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_FILE
}

# 发送报警函数
send_alert() {
    local usage=$1
    local message="【紧急报警】磁盘使用率已达 ${usage}%,持续超过 ${ALERT_MINUTES} 分钟!"
    
    # 检查是否已经发送过报警(避免重复报警)
    if [[ -f $ALERT_FLAG_FILE ]]; then
        return
    fi
    
    log_message "$message"
    
    # 方式1: 发送邮件(需要配置邮件服务)
    echo "$message" | mail -s "磁盘使用率报警" admin@example.com
    
    # 方式2: 系统通知
    which notify-send &>/dev/null && notify-send "磁盘报警" "$message"
    
    # 方式3: 写入系统日志
    logger -t "DiskMonitor" "$message"
    
    # 方式4: 调用webhook(示例)
    # curl -X POST "https://your-webhook-url" -d "message=$message"
    
    # 创建报警标志文件
    touch $ALERT_FLAG_FILE
}

# 主监控循环
monitor_disk() {
    while true; do
        # 获取磁盘使用率
        usage=$(df -h $CHECK_PARTITION | tail -1 | awk '{print $5}' | sed 's/%//')
        
        # 检查是否成功获取使用率
        if [[ -z "$usage" ]] || ! [[ "$usage" =~ ^[0-9]+$ ]]; then
            log_message "错误: 无法获取磁盘使用率"
            sleep 60
            continue
        fi
        
        # 读取计数器
        if [[ -f $COUNTER_FILE ]]; then
            counter=$(cat $COUNTER_FILE)
        else
            counter=0
        fi
        
        # 判断使用率是否超标
        if [[ $usage -gt $THRESHOLD ]]; then
            counter=$((counter + 1))
            log_message "警告: 磁盘使用率 ${usage}% (阈值: ${THRESHOLD}%),已持续 ${counter} 分钟"
            
            # 达到报警条件
            if [[ $counter -ge $ALERT_MINUTES ]]; then
                send_alert $usage
            fi
        else
            # 使用率正常,重置计数器
            if [[ $counter -gt 0 ]]; then
                log_message "恢复: 磁盘使用率 ${usage}%,计数器已重置"
            fi
            counter=0
            
            # 删除报警标志文件
            [[ -f $ALERT_FLAG_FILE ]] && rm -f $ALERT_FLAG_FILE
        fi
        
        # 保存计数器
        echo $counter > $COUNTER_FILE
        
        # 等待60秒
        sleep 60
    done
}

# 脚本入口
main() {
    log_message "磁盘监控脚本启动,监控分区: $CHECK_PARTITION"
    monitor_disk
}

# 执行主函数
main

1. 脚本部署

Bash
                    # 创建脚本文件
sudo vim /usr/local/bin/disk_monitor.sh

# 添加执行权限
sudo chmod +x /usr/local/bin/disk_monitor.sh

# 创建日志目录(如果不存在)
sudo touch /var/log/disk_monitor.log
sudo chmod 644 /var/log/disk_monitor.log

2. 配置开机自启动(systemd方式)

Service配置
                    # 创建 systemd 服务文件
sudo vim /etc/systemd/system/disk-monitor.service

# 添加以下内容:
[Unit]
Description=Disk Usage Monitor Service
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/disk_monitor.sh
Restart=always
RestartSec=10
User=root

[Install]
WantedBy=multi-user.target
Bash
                    # 重载 systemd 配置
sudo systemctl daemon-reload

# 启动服务
sudo systemctl start disk-monitor

# 设置开机自启
sudo systemctl enable disk-monitor

# 查看服务状态
sudo systemctl status disk-monitor

3. 使用crontab方式(替代方案)

Crontab
                    # 编辑 crontab
crontab -e

# 添加每分钟执行一次(将脚本改为单次检查模式)
* * * * * /usr/local/bin/disk_monitor_once.sh

重要注意事项

权限问题:确保脚本有写入日志文件和临时文件的权限。建议使用 root 用户运行或配置适当的权限。
防止重复报警:脚本使用了报警标志文件(ALERT_FLAG_FILE)来防止重复发送报警。只有当使用率恢复正常后,标志文件才会被删除。
分区选择:可以通过修改 CHECK_PARTITION 变量来监控不同的分区,如 "/home"、"/var" 等。
邮件配置:要使用邮件报警功能,需要先配置系统的邮件服务(如 postfix、sendmail)。
资源消耗:虽然每分钟检查一次不会造成太大负担,但在生产环境中建议监控脚本本身的资源使用情况。

测试与验证

测试步骤:

测试命令
                        # 1. 前台运行脚本观察输出
bash /usr/local/bin/disk_monitor.sh

# 2. 模拟高使用率(创建大文件)
dd if=/dev/zero of=/tmp/testfile bs=1M count=1000

# 3. 查看日志
tail -f /var/log/disk_monitor.log

# 4. 查看计数器文件
cat /tmp/disk_alert_counter.txt

# 5. 测试完成后清理
rm -f /tmp/testfile

调试技巧:

使用 set -x 开启调试模式,查看每一步执行

临时降低阈值(如改为20%)方便测试

缩短报警时间(如改为2分钟)加快测试速度

使用 echo 替代实际报警操作进行测试

1. 多分区监控

可以扩展脚本同时监控多个分区:

Shell
                    PARTITIONS=("/" "/home" "/var")

for partition in "${PARTITIONS[@]}"; do
    # 对每个分区分别检查
done

2. 集成监控系统

可以将报警信息发送到专业监控系统:

Prometheus + Alertmanager

Zabbix

Nagios

钉钉、企业微信机器人

3. 智能阈值

根据历史数据动态调整阈值,避免误报:

同分类 · 其他命令文档