企业级存储优化实战指南
📖 目录导读
为什么需要大文件自动清理?
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 必须规避的三大错误
-
误删系统文件
- 永远不要对 ,
/etc,/usr等系统目录执行递归扫描 - 设置白名单模式:
find使用-path排除系统路径
- 永远不要对 ,
-
删除正在写入的文件
# 错误做法:直接删除当前进程的文件会导致进程崩溃 rm /proc/1234/fd/3 # 危险! # 正确做法:使用lsof检查文件占用 lsof /data/logs/access.log | grep -q "mysqld" || rm /data/logs/access.log
-
权限不足导致任务失败
- 使用
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。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播