定时扫描并清理大文件脚本

wen 实用脚本 3

企业级存储优化实战指南

📖 目录导读

  1. 为什么需要大文件自动清理?
  2. 核心脚本设计原理
  3. 手把手编写扫描清理脚本
  4. 定时任务配置方法
  5. 安全风险与避坑指南
  6. 常见问题FAQ

为什么需要大文件自动清理?

Q:手动清理和脚本清理有什么区别?
A:大型服务器或NAS存储中,日志、临时文件、压缩包等大文件会迅速消耗磁盘空间,手动查找不仅效率极低,且容易误删重要数据,定时脚本能实现:

定时扫描并清理大文件脚本

  • 按阈值(如>100MB)自动扫描
  • 按最后修改时间(如30天未访问)过滤
  • 自动执行删除/归档/压缩动作
  • 生成清理报告邮件通知

Q:哪些场景最需要此脚本?

  • 日志服务器(每天产生GB级日志)
  • 媒体编辑工作站(渲染缓存堆积)
  • 企业备份NAS(旧备份未自动轮替)
  • 开发测试环境(依赖包和构建产物)

核心脚本设计原理

1 数据流架构

[磁盘扫描] → [过滤规则引擎] → [操作决策] → [执行清理] → [日志记录]

2 关键参数设计

参数 示例值 说明
扫描路径 /data/logs/ 建议细化到目录,避免扫描系统分区
文件大小阈值 500MB 超过该值才进入候选列表
时间阈值 90天 仅处理指定时间内未修改的文件
排除模式 .lock,.pid 保护锁文件和进程文件
操作类型 delete/archive 删除或压缩后移动到归档目录

3 性能优化要点

  • 使用find命令的-size参数替代逐文件stat调用
  • 对大目录启用-maxdepth限制递归深度
  • 采用xargs -P实现并行处理(适合SSD场景)

手把手编写扫描清理脚本

1 基础版:单目录清理脚本

#!/bin/bash
# clean_large_files.sh
TARGET_DIR="/var/log/app"
THRESHOLD="+500M"
AGE="+30"
EXCLUDE_PATTERN="*.gz"
echo "[$(date)] 开始扫描 $TARGET_DIR 中超过 ${THRESHOLD} 且 ${AGE} 天未修改的文件"
find "$TARGET_DIR" -type f -size $THRESHOLD -mtime $AGE ! -name "$EXCLUDE_PATTERN" -print0 | \
while IFS= read -r -d '' file; do
    filesize=$(du -h "$file" | cut -f1)
    echo "  [清理] $file (大小: $filesize)"
    # 安全模式:先移动到回收站
    mv "$file" "/tmp/recycle_bin/$(basename $file).$(date +%Y%m%d%H%M%S)"
done
# 压缩回收站(可选)
tar -czf "/backup/archive_$(date +%Y%m%d).tar.gz" -C /tmp/recycle_bin .
rm -rf /tmp/recycle_bin/*
echo "[$(date)] 清理完成,备份已存放至 /backup"

2 增强版:多规则配置文件

#!/bin/bash
# config_cleaner.sh
CONFIG_FILE="/etc/cleanup/clean_rules.conf"
# 配置文件格式示例:
# /data/logs 100M 90 delete *.zip
# /tmp/cache  500M  7 archive *.tmp
while IFS=' ' read -r dir size age action exclude; do
    [[ "$dir" == "#"* ]] && continue  # 跳过注释
    echo "处理目录: $dir (标准: >$size, 修改>$age天, 排除:$exclude)"
    find "$dir" -type f -size "+$size" -mtime "+$age" ! -name "$exclude" | \
    while read file; do
        case "$action" in
            delete)
                rm -f "$file"
                logger "已删除过期大文件: $file"
                ;;
            archive)
                gzip "$file" && mv "$file.gz" "/archive/$(basename $file).gz"
                ;;
        esac
    done
done < "$CONFIG_FILE"

3 跨平台:Python版(支持Windows/Linux)

#!/usr/bin/env python3
# cross_platform_cleaner.py
import os, time, logging
from pathlib import Path
def clean_large_files(root_dir, max_size_mb=500, max_age_days=90, exclude_exts=[], action='delete'):
    logging.basicConfig(filename='cleaner.log', level=logging.INFO)
    now = time.time()
    max_age_seconds = max_age_days * 86400
    for file_path in Path(root_dir).rglob('*'):
        if file_path.is_file():
            ext = file_path.suffix.lower()
            if ext in ['.'+e for e in exclude_exts]:
                continue
            size_mb = file_path.stat().st_size / (1024*1024)
            age_seconds = now - file_path.stat().st_mtime
            if size_mb >= max_size_mb and age_seconds >= max_age_seconds:
                if action == 'delete':
                    file_path.unlink()
                    logging.info(f"已删除: {file_path} ({size_mb:.2f}MB)")
                elif action == 'archive':
                    file_path.rename(file_path.with_suffix(file_path.suffix+'.old'))
if __name__ == '__main__':
    clean_large_files('/var/log', max_size_mb=200, exclude_exts=['gz','zip'])

定时任务配置方法

1 Linux crontab 配置

# 每天凌晨2点执行清理
0 2 * * * /usr/local/bin/clean_large_files.sh >> /var/log/cleanup.log 2>&1
# 每周日凌晨3点执行深度清理
0 3 * * 0 /usr/local/bin/config_cleaner.sh

2 Windows 任务计划程序

触发器:每天 01:00
操作:启动程序 "python.exe"
参数:"D:\scripts\cross_platform_cleaner.py"
起始于:D:\scripts

3 容器化方案(Docker)

services:
  cleaner:
    image: alpine:latest
    volumes:
      - /data:/target
      - ./scripts:/scripts
    command: >
      sh -c "apk add --no-cache bash &&
             crond -f -l 2 &&
             /scripts/clean_large_files.sh"
    environment:
      - CHECK_INTERVAL=3600

安全风险与避坑指南

1 必须规避的三大错误

  1. 误删系统文件

    • 永远不要对 , /etc, /usr 等系统目录执行递归扫描
    • 设置白名单模式:find使用-path排除系统路径
  2. 删除正在写入的文件

    # 错误做法:直接删除当前进程的文件会导致进程崩溃
    rm /proc/1234/fd/3  # 危险!
    # 正确做法:使用lsof检查文件占用
    lsof /data/logs/access.log | grep -q "mysqld" || rm /data/logs/access.log
  3. 权限不足导致任务失败

    • 使用sudo运行脚本时注意环境变量继承
    • 日志目录权限:chmod 640 /var/log/cleanup.log

2 数据恢复保障方案

# 删除前创建软链接备份
BACKUP_DIR="/backup/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
while read file; do
    ln -s "$file" "$BACKUP_DIR/$(basename $file | md5sum | cut -d' ' -f1)"
done < <(find /target -size +500M)
# 恢复时只需读取软链接的原始路径

常见问题FAQ

Q1:脚本扫描导致CPU和磁盘IO飙升怎么办?
→ 添加nice命令降低优先级:
nice -n 19 find /data -size +500M | xargs -P 1 rm
→ 在find中使用-maxdepth减少扫描范围
→ 对日志类文件可使用inotify实时监控替代全量扫描

Q2:如何只清理日志目录但保留最近7天的日志?

# 利用mtime参数
find /var/log -name "*.log" -mtime +7 -size +10M -delete
# 更精确:保留最新版本
ls -1t /var/log/*.log | tail -n +30 | xargs rm

Q3:清理后如何发送报告?

# 使用mailx发送HTML报告
{
echo "Subject: Disk Cleanup Report $(date)"
echo "Content-Type: text/html"
echo ""
echo "<h3>清理摘要</h3>"
echo "<table border=1><tr><th>文件</th><th>大小</th><th>操作</th></tr>"
while read file; do
    echo "<tr><td>$file</td><td>$(du -h "$file" | cut -f1)</td><td>已删除</td></tr>"
done < /tmp/deleted_files.txt
echo "</table>"
} | /usr/sbin/sendmail -t "admin@example.com"

Q4:遇到只读文件系统如何处理?
→ 在脚本中加入重试逻辑:

for i in range(3):
    try:
        os.unlink(file_path)
        break
    except PermissionError:
        subprocess.run(['chattr', '-i', file_path])
        time.sleep(5)

Q5:如何对特定用户(如mysql)的文件设置保留策略?

# 使用find的-user参数
find /home -user mysql -size +1G -mtime +90 -exec rm {} \;
# 或使用acl权限控制
setfacl -m u:mysql:--- /data/expired_dir

专业建议:在生产环境部署前,务必在测试环境运行脚本的--dry-run模式,并开启脚本的日志功能,建议每周检查cleanup.log文件,结合磁盘使用率趋势图动态调整清理策略,对于关键业务数据,始终优先使用archive动作而非delete

抱歉,评论功能暂时关闭!