自动化脚本如何清理快照文件

wen 实用脚本 1

本文目录导读:

自动化脚本如何清理快照文件

  1. 核心原则
  2. 方案一:Linux/Unix 下清理本地文件系统快照
  3. 方案二:清理数据库快照(以 MySQL/XtraBackup 为例)
  4. 方案三:清理云存储快照(AWS EBS / OpenStack Cinder)
  5. 方案四:清理 Docker/容器快照
  6. 方案五:清理 VMware / VirtualBox 快照
  7. 最佳实践:综合清理脚本模板(Dry-Run + 发送警报)
  8. 自动化执行(Crontab / Scheduled Tasks)
  9. 常见陷阱与解决

针对自动化清理快照文件的需求,常用的方法包括按时间过期按数量限制以及按空间配额,以下是几种常见的自动化脚本实现方案,涵盖 Linux/Unix 环境、Windows 环境以及云存储场景。

核心原则

  1. 不要删除正在使用的快照:尤其是数据库或虚拟机快照,需确保脚本与业务状态协同。
  2. 保留策略:建议采用“阶梯保留”,保留最近 7 天的每日快照、4 周的每周快照。
  3. 日志和确认:清理前先打印删除列表(dry-run 模式),确认无误后再执行。

Linux/Unix 下清理本地文件系统快照

假设你的快照文件遵循统一的命名规则,snapshot-2025-01-01.tar.gz

按时间清理(保留最近 N 天)

#!/bin/bash
# delete_old_snapshots.sh
# 功能:删除 /var/backups/snapshots/ 目录下 7 天前的 .snap 文件
SNAPSHOT_DIR="/var/backups/snapshots"
RETENTION_DAYS=7
LOG_FILE="/var/log/cleanup_snapshot.log"
echo "$(date) - Starting old snapshot cleanup (older than $RETENTION_DAYS days)" >> $LOG_FILE
# 使用 find 命令查找并删除
# 建议先使用 -print 查看,确认无误后改为 -delete 或 -exec rm {} \;
find "$SNAPSHOT_DIR" -name "*.snap" -type f -mtime +$RETENTION_DAYS -print -delete >> $LOG_FILE 2>&1
echo "$(date) - Cleanup completed." >> $LOG_FILE

进阶:Dry-Run 模式(安全测试)

find "$SNAPSHOT_DIR" -name "*.snap" -type f -mtime +$RETENTION_DAYS -print

按数量清理(保留最近 N 个)

如果快照是按时间序列命名(如 snapshot-001 snapshot-002),使用 ls -t 排序后删除多余文件。

#!/bin/bash
SNAPSHOT_DIR="/var/backups/snapshots"
MAX_SNAPSHOTS=10
FILE_PATTERN="snapshot-*"
cd "$SNAPSHOT_DIR" || exit
# 按修改时间排序,列出所有匹配文件
file_count=$(ls -1t $FILE_PATTERN 2>/dev/null | wc -l)
if [ "$file_count" -gt "$MAX_SNAPSHOTS" ]; then
    # 删除最旧的 (file_count - MAX_SNAPSHOTS) 个文件
    ls -1t $FILE_PATTERN | tail -n +$((MAX_SNAPSHOTS + 1)) | xargs rm -f
    echo "$(date) - Deleted $((file_count - MAX_SNAPSHOTS)) old snapshots."
else
    echo "$(date) - Current snapshots ($file_count) within limit ($MAX_SNAPSHOTS). Skipping."
fi

清理数据库快照(以 MySQL/XtraBackup 为例)

数据库的增量/全量快照通常是一个目录,而非单个文件,建议结合 LVM 快照或 Percona XtraBackup 的 --incremental-basedir

示例脚本:删除过期的 XtraBackup 全量备份目录

#!/bin/bash
BACKUP_BASE="/data/backups/mysql"
RETENTION_DAYS=30
# 删除超过 30 天(且非当前备份)的目录
find "$BACKUP_BASE" -maxdepth 1 -type d -name "full-*" -mtime +$RETENTION_DAYS | while read dir; do
    echo "$(date) - Removing old backup directory: $dir"
    rm -rf "$dir"
done

安全注意:删除 rm -rf 时应确认目录名模式,避免误删。


清理云存储快照(AWS EBS / OpenStack Cinder)

AWS EBS 快照清理(使用 AWS CLI)

#!/bin/bash
# 删除所有超过 7 天的、状态为 completed 的 EBS 快照
RETENTION_DAYS=7
CUTOFF_DATE=$(date -d "-$RETENTION_DAYS days" +%Y-%m-%d)
aws ec2 describe-snapshots --owner-ids self \
    --query "Snapshots[?StartTime<='$CUTOFF_DATE' && State=='completed'].[SnapshotId]" \
    --output text | while read snapshot_id; do
        echo "Deleting snapshot: $snapshot_id"
        aws ec2 delete-snapshot --snapshot-id "$snapshot_id"
done

OpenStack Cinder 快照清理(使用 OpenStack CLI)

#!/bin/bash
# 删除所有超过 30 天的 Cinder 快照
openstack snapshot list --all-projects --long -f value -c ID -c Name -c Created | while read line; do
    snapshot_id=$(echo $line | awk '{print $1}')
    created_at=$(echo $line | awk '{print $3}')
    snapshot_age_days=$(( ($(date +%s) - $(date -d "$created_at" +%s)) / 86400 ))
    if [ "$snapshot_age_days" -gt 30 ]; then
        echo "Deleting snapshot $snapshot_id (created $created_at)"
        openstack snapshot delete "$snapshot_id"
    fi
done

清理 Docker/容器快照

快照”是 Docker 镜像或容器层,使用 Docker 自带清理命令:

#!/bin/bash
# 清理所有未使用(dangling)的镜像和容器快照层
docker system prune -a -f --filter "until=24h" 2>&1 | logger -t docker-cleanup
# 手动清理过期的镜像(按标签或时间)
docker image prune -a --filter "until=72h" -f

清理 VMware / VirtualBox 快照

VMware 快照实质上是多个 .vmdk 文件,不推荐直接用 rm 删除,会导致虚拟机损坏。

推荐方法:调用 VMware 命令行工具 vmware-cmd 或 PowerCLI。

#!/bin/bash
# 使用 vmware-cmd(ESXi环境)移除所有快照
vmware-cmd <path_to_vm.vmx> removesnapshots

如果是在批量管理平台(如 vSphere),建议编写 PowerCLI 脚本。


最佳实践:综合清理脚本模板(Dry-Run + 发送警报)

#!/bin/bash
# comprehensive_snapshot_cleaner.sh
SNAPSHOT_DIR="/var/snapshots"
RETENTION_DAYS=14
DRY_RUN=true   # 改 false 执行删除
echo "========================================="
echo "Snapshot Cleanup Report - $(date)"
echo "Target directory: $SNAPSHOT_DIR"
echo "Retention days: $RETENTION_DAYS"
echo "Dry run mode: $DRY_RUN"
echo "========================================="
if [ "$DRY_RUN" = true ]; then
    echo "[DRY RUN] Files that would be deleted:"
    find "$SNAPSHOT_DIR" -name "snapshot-*" -type f -mtime +$RETENTION_DAYS -print
else
    deleted_count=$(find "$SNAPSHOT_DIR" -name "snapshot-*" -type f -mtime +$RETENTION_DAYS -print -delete | wc -l)
    echo "Deleted $deleted_count snapshot(s)."
    # 可选:发送告警或记录到监控系统
    # curl -X POST -H "..." -d '{"text":"cleaned $deleted_count snapshots"}' https://alerts.example.com
fi

自动化执行(Crontab / Scheduled Tasks)

  • Linux(crontab):
    0 2 * * * /usr/local/bin/delete_old_snapshots.sh
  • Windows(任务计划程序):创建一个每天凌晨 2 点执行的 PowerShell 脚本。

常见陷阱与解决

问题 解决方案
快照被其他进程占用(如数据库) 先检查锁文件,或使用 lsof,在脚本开始处添加 fuser -s /path/to/snapshot || exit 1
忘记更新保留策略 将保留天数作为脚本参数($1)传入,或从配置文件读取
云 API 限流 在 AWS/OpenStack 脚本中添加重试逻辑(sleep 1)和错误重试
误删当前正在使用的快照 先备份快照元数据清单,标记保护快照(如 AWS 快照),脚本中显式跳过标记过的快照
  • 本地文件快照find + mtime 是最简单高效的方式。
  • 数据库/系统快照:优先使用应用自身提供的清理工具(如 xtrabackup --decompress --remove-all)。
  • 云快照:使用 CLI 工具按 StartTime 筛选并批量删除。
  • 安全第一:务必在脚本中增加 dry-run 模式、日志记录和排除保护快照的逻辑。

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