磁盘空间深度检查脚本

点击查看代码
#!/bin/bash
# 文件名:disk_check_v2.sh   用法:bash disk_check_v2.sh
# 功能:磁盘/Inode/日志/临时文件/大文件 快速巡检 + 清理建议
#############################################################

###################  可改配置  ###################
# 巡检报告保存路径,包含当前日期时间(格式:年-月-日_时-分)
REPORT="/var/log/disk_check_$(date +%F_%H%M).log"
DISK_WARN=80        # 磁盘使用率告警阈值(百分比),超过此值触发警告
INODE_WARN=80       # Inode使用率告警阈值(百分比),超过此值触发警告
BIG_FILE="500M"     # 大文件判定阈值,超过此大小的文件将被标记为大文件
# 指定需要检查的分区挂载点(仅检查这些路径的磁盘和Inode使用情况)
TARGET_MOUNTS=("/run" "/" "/dev/shm" "/run/lock" "/boot")
##################################################

# 定义颜色变量,用于终端输出格式化(绿色:正常,黄色:警告,红色:错误)
RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'; NC='\033[0m'  # NC:重置颜色

# 日志输出函数:带时间戳,同时输出到终端和报告文件
log()     { echo -e "[$(date '+%F %T')] $1" | tee -a "$REPORT"; }
# 正常状态日志:带绿色[OK]标识
log_ok()  { echo -e "[$(date '+%F %T')] ${GREEN}[OK]${NC} $1" | tee -a "$REPORT"; }
# 警告状态日志:带黄色[WARN]标识
log_warn(){ echo -e "[$(date '+%F %T')] ${YELLOW}[WARN]${NC} $1" | tee -a "$REPORT"; }
# 错误状态日志:带红色[ERR]标识
log_err() { echo -e "[$(date '+%F %T')] ${RED}[ERR]${NC} $1" | tee -a "$REPORT"; }

# 1. 磁盘使用率检查(仅指定分区)
check_disk(){
    log ">>>> 1. 磁盘使用率(指定分区)"  # 标记当前检查模块
    
    # 循环遍历需要检查的挂载点
    for mount in "${TARGET_MOUNTS[@]}"; do
        # 获取分区信息:通过df -h查询磁盘使用情况,筛选包含目标挂载点的行
        # 正则匹配"^Filesystem"(标题行)或" $mount$"(精确匹配挂载点,避免子路径干扰)
        df_info=$(df -h | grep -E "^Filesystem| $mount$")
        
        # 如果未找到该分区信息,记录警告并跳过
        if [ -z "$df_info" ]; then
            log_warn "分区 $mount 不存在或未挂载"
            echo "" | tee -a "$REPORT"  # 输出空行分隔不同分区的检查结果
            continue
        fi
        
        # 提取分区详细信息(排除标题行,只取数据行)
        info=$(echo "$df_info" | tail -n 1)
        # 从数据行中解析各字段(通过awk按空格分割)
        fs=$(echo "$info" | awk '{print $1}')      # 设备名(如/dev/sda1)
        size=$(echo "$info" | awk '{print $2}')    # 总容量(如50G)
        used=$(echo "$info" | awk '{print $3}')    # 已用空间(如10G)
        avail=$(echo "$info" | awk '{print $4}')   # 可用空间(如40G)
        use=$(echo "$info" | awk '{print $5}')     # 使用率(如20%)
        
        # 去除使用率中的百分号,转为数字用于比较(如"20%" -> 20)
        usage=${use%\%}
        # 记录当前分区的基本信息
        log "分区: $mount  设备: $fs  使用率: $usage%  总大小: $size  已用: $used  可用: $avail"
        
        # 如果使用率超过告警阈值,触发错误处理
        if [ "$usage" -gt "$DISK_WARN" ]; then
            log_err "磁盘使用率超阈值!"  # 标记错误状态
            
            # 输出该分区下占用空间最大的前10个目录(便于定位大文件来源)
            echo "  占用空间 Top10 目录:" | tee -a "$REPORT"
            # du -sh:显示目录大小(人类可读格式);sort -hr:按大小倒序;head -10:取前10
            du -sh "$mount"/* 2>/dev/null | sort -hr | head -10 | tee -a "$REPORT"
            
            # 输出该分区下超过设定阈值的大文件列表(含大小、路径、修改时间)
            echo "  大文件(>$BIG_FILE)列表:" | tee -a "$REPORT"
            # find命令筛选大文件:-type f(文件)、-size +$BIG_FILE(超过阈值)
            # -printf:输出文件大小(字节)、路径、修改时间(年-月-日 时:分)
            # 后续通过sort排序、head取前10,最后用awk转换大小为MB并格式化输出
            find "$mount" -type f -size +$BIG_FILE 2>/dev/null \
              -printf "%s\t%p\t%TY-%Tm-%Td %TH:%TM\n" | \
              sort -nr | head -10 | \
              awk '{printf "  %8.2fMB  %s  %s\n",$1/1024/1024,$2,$3}' | tee -a "$REPORT"
        else
            log_ok "使用率正常"  # 使用率在阈值内,标记正常状态
        fi
        echo "" | tee -a "$REPORT"  # 输出空行分隔不同分区的检查结果
    done
}

# 2. Inode 使用率检查(仅指定分区)
check_inode(){
    log ">>>> 2. Inode 使用率(指定分区)"  # 标记当前检查模块
    
    # 循环遍历需要检查的挂载点
    for mount in "${TARGET_MOUNTS[@]}"; do
        # 获取Inode信息:通过df -i查询Inode使用情况,筛选包含目标挂载点的行
        df_info=$(df -i | grep -E "^Filesystem| $mount$")
        
        # 如果未找到该分区信息,记录警告并跳过
        if [ -z "$df_info" ]; then
            log_warn "分区 $mount 不存在或未挂载"
            echo "" | tee -a "$REPORT"  # 输出空行分隔不同分区的检查结果
            continue
        fi
        
        # 提取Inode详细信息(排除标题行,只取数据行)
        info=$(echo "$df_info" | tail -n 1)
        # 从数据行中解析各字段
        fs=$(echo "$info" | awk '{print $1}')      # 设备名
        itot=$(echo "$info" | awk '{print $2}')    # Inode总数量
        iused=$(echo "$info" | awk '{print $3}')   # 已使用的Inode数量
        ifree=$(echo "$info" | awk '{print $4}')   # 剩余的Inode数量
        iuse=$(echo "$info" | awk '{print $5}')    # Inode使用率(如30%)
        
        # 去除使用率中的百分号,转为数字用于比较
        usage=${iuse%\%}
        # 记录当前分区的Inode基本信息
        log "分区: $mount  设备: $fs  Inode使用率: $usage%  总数量: $itot  已用: $iused  可用: $ifree"
        
        # 如果Inode使用率超过告警阈值,触发错误处理(通常因小文件过多导致)
        if [ "$usage" -gt "$INODE_WARN" ]; then
            log_err "Inode 使用率超阈值!(小文件过多)"  # 标记错误状态
            
            # 输出该分区下包含文件数量最多的前10个目录(便于定位小文件来源)
            echo "  文件数 Top10 目录:" | tee -a "$REPORT"
            # find命令递归统计每个目录下的文件数量:
            # -xdev:限制在当前分区(不跨设备);-maxdepth 2:最多遍历2层目录
            # 对每个目录执行子shell:统计文件数并输出"数量 目录路径"
            # 最后通过sort排序、head取前10
            find "$mount" -xdev -type d -maxdepth 2 -exec sh -c 'echo $(find "$1" -xdev -type f 2>/dev/null | wc -l) $1' _ {} \; | \
              sort -nr | head -10 | tee -a "$REPORT"
        else
            log_ok "Inode 使用率正常"  # Inode使用率在阈值内,标记正常状态
        fi
        echo "" | tee -a "$REPORT"  # 输出空行分隔不同分区的检查结果
    done
}

# 3. 日志/临时文件 一键清理建议
suggest(){
    log ">>>> 3. 一键清理建议(可直接复制执行)"  # 标记当前模块
    
    # 输出预设的清理命令(通过cat <<'EOF'保留命令格式,避免变量解析)
    cat <<'EOF' | tee -a "$REPORT"
# 1. 压缩 30 天前旧日志(保留文件但减小体积)
find /var/log -type f -name "*.log" -mtime +30 -exec gzip {} \;

# 2. 清理7天未访问的/tmp临时文件(避免临时文件堆积)
find /tmp -type f -atime +7 -delete

# 3. 清理yum缓存(适用于CentOS/Rocky等RPM系系统)
yum clean all

# 4. 清理Docker未使用的镜像、容器、网络(释放Docker占用空间)
docker system prune -af

# 5. 清理journal日志(系统日志,保留最近7天)
journalctl --vacuum-time=7d

# 6. 手工删除大文件(需确认文件无用后执行,路径需替换)
# rm -f /path/to/bigfile.log
EOF
}

###################  主程序  ###################
# 输出报告头部信息(包含脚本版本和执行时间),同时写入报告文件
echo "========== 磁盘巡检 v2  $(date) ==========" | tee "$REPORT"
# 执行磁盘使用率检查
check_disk
# 执行Inode使用率检查
check_inode
# 输出清理建议
suggest
# 输出报告完成信息,提示报告保存路径
echo "========== 完成!报告:$REPORT ==========" | tee -a "$REPORT"

执行结果

点击查看代码
========== 磁盘巡检 v2  Mon Nov  3 04:32:24 PM CST 2025 ==========
[2025-11-03 16:32:24] >>>> 1. 磁盘使用率(指定分区)
[2025-11-03 16:32:24] 分区: /run  设备: tmpfs  使用率: 1%  总大小: 388M  已用: 2.3M  可用: 386M
[2025-11-03 16:32:24] [OK] 使用率正常

[2025-11-03 16:32:24] 分区: /  设备: /dev/mapper/ubuntu--vg-ubuntu--lv  使用率: 30%  总大小: 48G  已用: 14G  可用: 32G
[2025-11-03 16:32:24] [OK] 使用率正常

[2025-11-03 16:32:24] 分区: /dev/shm  设备: tmpfs  使用率: 0%  总大小: 1.9G  已用: 0  可用: 1.9G
[2025-11-03 16:32:24] [OK] 使用率正常

[2025-11-03 16:32:24] 分区: /run/lock  设备: tmpfs  使用率: 0%  总大小: 5.0M  已用: 0  可用: 5.0M
[2025-11-03 16:32:24] [OK] 使用率正常

[2025-11-03 16:32:24] 分区: /boot  设备: /dev/sda2  使用率: 14%  总大小: 2.0G  已用: 247M  可用: 1.6G
[2025-11-03 16:32:24] [OK] 使用率正常

[2025-11-03 16:32:24] >>>> 2. Inode 使用率(指定分区)
[2025-11-03 16:32:24] 分区: /run  设备: tmpfs  Inode使用率: 1%  总数量: 496106  已用: 1133  可用: 494973
[2025-11-03 16:32:24] [OK] Inode 使用率正常

[2025-11-03 16:32:24] 分区: /  设备: /dev/mapper/ubuntu--vg-ubuntu--lv  Inode使用率: 5%  总数量: 3211264  已用: 157212  可用: 3054052
[2025-11-03 16:32:24] [OK] Inode 使用率正常

[2025-11-03 16:32:25] 分区: /dev/shm  设备: tmpfs  Inode使用率: 1%  总数量: 496106  已用: 1  可用: 496105
[2025-11-03 16:32:25] [OK] Inode 使用率正常

[2025-11-03 16:32:25] 分区: /run/lock  设备: tmpfs  Inode使用率: 1%  总数量: 496106  已用: 4  可用: 496102
[2025-11-03 16:32:25] [OK] Inode 使用率正常

[2025-11-03 16:32:25] 分区: /boot  设备: /dev/sda2  Inode使用率: 1%  总数量: 131072  已用: 320  可用: 130752
[2025-11-03 16:32:25] [OK] Inode 使用率正常

[2025-11-03 16:32:25] >>>> 3. 一键清理建议(可直接复制执行)
# 1. 压缩 30 天前旧日志
find /var/log -type f -name "*.log" -mtime +30 -exec gzip {} \;

# 2. 清 7 天未访问的 /tmp 文件
find /tmp -type f -atime +7 -delete

# 3. 清 yum 缓存(CentOS/Rocky)
yum clean all

# 4. 清 Docker 未用镜像/容器/网络(如装 Docker)
docker system prune -af

# 5. 清 journal 日志(保留最近 7 天)
journalctl --vacuum-time=7d

# 6. 手工删除大文件(务必确认路径)
# rm -f /path/to/bigfile.log
========== 完成!报告:/var/log/disk_check_2025-11-03_1632.log ==========
posted @ 2025-11-03 16:39  你腿别抖了  阅读(34)  评论(0)    收藏  举报