用脚本自动化完成每日增量备份与清理旧文件,核心方案是组合使用rsync做增量同步与find命令按时间戳清理过期文件,再交由计划任务定时触发,全程无需人工干预。
为什么必须同时解决备份与清理两个问题
很多运维新手和站长朋友都踩过同一个坑:只写了备份脚本,忘了清理旧文件,于是磁盘空间一天天被占满,直到某天备份任务报错“No space left on device”,才发现问题,我见过太多类似的案例,备份文件堆积了三个月没人管,最终把服务器磁盘撑爆,连业务日志都写不进去了。
备份和清理不是两件事,而是同一套自动化脚本里的左右手,增量备份保证每天的数据变化被安全记录,清理任务则确保备份仓库存活空间,让备份任务能长久跑下去,业内专家指出,多数备份失败事故根源不在备份本身,而是存储空间耗尽。
设计脚本的第一步不是写rsync,而是想清楚文件保留策略,比如保留最近7天的每日增量、最近4周的每周全量,超过窗口期的文件直接删除,策略定了,脚本逻辑也就顺了。
每日增量备份脚本怎么写
增量备份与全量备份区别是什么
先解决一个常见疑惑:增量备份与全量备份区别是什么,全量备份每次把所有文件完整复制一遍,耗时和空间成本都很高,增量备份只同步自上次备份以来发生变化的部分,速度大幅提升,尤其适合数据量大的服务器。
rsync是Linux环境下的经典工具,天然支持增量同步,它通过对比源和目标端的文件大小、修改时间,只传输有差异的数据块,配合--link-dest参数还能实现“伪增量”效果:每次都生成一个完整目录结构,但未变化的文件用硬链接指向上一次备份,磁盘占用几乎为零。
每日增量备份脚本的完整实现
以下是一个笔者在多个生产环境运行过的脚本模板,适合Linux服务器:
#!/bin/bash
# 每日增量备份脚本 - 保留7天增量 + 4周全量
BACKUP_BASE="/backup/data"
SOURCE_DIR="/var/www/html"
DATE=$(date +%Y-%m-%d)
WEEKDAY=$(date +%u) # 1-7,代表周一到周日
# 如果今天是周日,做全量备份
if [ "$WEEKDAY" -eq 7 ]; then
rsync -avz --delete "$SOURCE_DIR" "$BACKUP_BASE/full-$DATE/"
# 清理超过4周的旧全量备份
find "$BACKUP_BASE" -maxdepth 1 -type d -name "full-" -mtime +28 -exec rm -rf {} ;
else
# 找到最近一次全量备份作为基准
LAST_FULL=$(ls -d "$BACKUP_BASE"/full- 2>/dev/null | tail -1)
rsync -avz --link-dest="$LAST_FULL" "$SOURCE_DIR" "$BACKUP_BASE/inc-$DATE/"
fi
# 清理超过7天的增量备份目录
find "$BACKUP_BASE" -maxdepth 1 -type d -name "inc-" -mtime +7 -exec rm -rf {} ;
这段脚本做了三件事:周日执行全量备份并清理超过28天的旧全量包;其余六天执行增量备份,硬链接复用未变化文件;最后统一清理超过7天的增量目录。
执行权限记得加上:chmod +x backup.sh,建议先在测试目录跑一遍,确认逻辑无误再上生产。
清理旧文件的策略与命令实现
基于时间戳的清理方法
清理逻辑的核心是find命令的-mtime参数,它按文件修改时间筛选目标,组合-exec或-delete直接删除,也可以先输出列表确认再删。
常用形式如下:
# 删除修改时间超过N天的文件
find /backup/data -type f -mtime +30 -delete
# 按目录名模式匹配,删除历史备份目录
find /backup/data -maxdepth 1 -type d -name "inc-" -mtime +7 -exec rm -rf {} ;
# 保留最近N个备份文件,删除更早版本
ls -1t /backup/data/.tar.gz | tail -n +8 | xargs rm -f
第三种方式按文件数量而非时间窗口控制保留数,适合备份频率不固定的场景。
清理旧文件的几种常见策略对比
不同业务场景适合不同的清理策略,整理如下:
| 策略 | 适用场景 | 优缺点 |
|---|---|---|
| 按天数清理(-mtime) | 固定频率备份 | 逻辑简单,但备份中断会误删新文件 |
| 按数量保留 | 频率不固定 | 永远保留最近N份,空间消耗可控 |
| 按大小配额清理 | 存储有限 | 需额外判断磁盘阈值,脚本略复杂 |
| 全量+增量复合策略 | 数据量较大 | 兼顾恢复速度与空间占用 |
多数情况下,按天数清理配合复合备份策略已经足够,如果磁盘紧张,可以在脚本开头加一条磁盘使用率判断,超过阈值时提前触发清理。
如何在Windows和Linux下实现定时触发
Linux系统用crontab
脚本写好后,编辑用户的crontab文件:
crontab -e
加入以下行,表示每天凌晨2点执行:
0 2 /usr/local/bin/backup.sh >> /backup/log/backup.log 2>&1
建议将标准输出和错误输出都重定向到日志文件,方便事后排查,如果服务器上跑着nginx或数据库,备份前可以先调用对应命令做内存数据落盘,防止文件处于写入中间态。
Windows计划任务设置定时备份
Windows环境下没有rsync,通常使用robocopy配合PowerShell脚本实现类似效果,先另存为backup.ps1:
$source = "D:wwwroot"
$backup = "D:backupdata"
$date = Get-Date -Format "yyyy-MM-dd"
$keepDays = 7
# robocopy增量复制(/MIR镜像模式按需调整)
robocopy $source "$backup$date" /E /R:2 /W:2
# 清理7天前的备份目录
Get-ChildItem $backup -Directory | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$keepDays) } | Remove-Item -Recurse -Force
然后通过任务计划程序创建基本任务,触发器选择“每天”,操作选择“启动程序”,程序填powershell.exe,参数填-ExecutionPolicy Bypass -File D:scriptsbackup.ps1。
很多中小企业服务器跑在Windows Server上,Windows计划任务设置定时备份是刚需,这里有个注意点:PowerShell执行策略默认可能拦截脚本,务必显式传入-ExecutionPolicy Bypass参数。
macOS环境怎么处理
macOS用户也不在少数,尤其个人开发者和设计工作室,macOS自带rsync(新版本是rsync的BSD变体,参数略有差异)和launchd任务管理,如果用Homebrew安装rsync,则与Linux版本行为一致。
launchd配置比crontab啰嗦,但支持更精细的调度条件,在~/Library/LaunchAgents下创建com.example.backup.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.example.backup</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/backup.sh</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>3</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</dict>
</plist>
执行launchctl load加载后,每天凌晨3点自动触发,macOS用户写脚本时注意date命令的-j参数与Linux不同,格式化日期的方式略有区别。
自动化脚本运行前后的关键避坑点
备份完整性和恢复演练
脚本自动化不代表万事大吉,每周至少手动执行一次恢复验证,把某天的备份目录解压到临时目录,检查关键文件是否可读,如果备份任务运行半年却从没恢复过,那这个备份的有效性基本等于零。
对于数据库类应用,建议在备份函数里嵌套数据库导出命令,以MySQL为例:
mysqldump -u root -p"$DB_PASS" --single-transaction mydb > /tmp/mydb.sql rsync -avz /tmp/mydb.sql "$BACKUP_BASE/db/$DATE.sql"
否则只备份数据文件目录,很可能得到一份不一致的数据库快照,恢复时会出各种诡异问题。
日志和告警机制
脚本任务单跑不够,失败要有感知,最简单的方式是在脚本末尾追加一行判断,备份失败时发送告警:
if [ $? -eq 0 ]; then
echo "Backup OK at $(date)" >> /backup/log/backup.log
else
# 通过mailx或curl调到企业微信机器人
curl -X POST "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY"
-H 'Content-Type: application/json'
-d '{"msgtype":"text","text":{"content":"备份失败,请检查服务器!"}}'
fi
这个机制帮我在凌晨3点收到过多次硬盘预警,每次都是空间不足先于备份失败暴露问题,近年来固态硬盘价格走低,不少用户开始加购NAS或私有云,但跨设备备份的脚本逻辑同样适用。
Q&A:关于每日增量备份脚本的常见疑问
备份脚本没执行怎么办
先检查计划任务是否在跑,Linux下执行crontab -l查看条目,systemctl status cron确认服务状态,再看日志文件末尾有没有报错信息,权限问题是高频故障源脚本没加执行权限或者在root的crontab里引用了普通用户的PATH路径,都会导致任务静默失败。
增量备份误删了原文件能否恢复
如果rsync带了--delete参数,源端删除的文件会在下一次备份时同步删除,恢复思路是:立刻停止对源目录的写入,从最近的增量备份目录中找回文件,但如果备份周期结束时清理任务已运行,旧版本可能被覆盖,所以重要场景建议全量备份保留窗口拉长到6周,增量保留14天,给恢复留足操作空间。
增量备份与差异备份有什么区别
增量备份依赖上一次备份(无论增量还是全量),恢复时需要串联整个链条;差异备份每次基于最近一次全量备份,恢复时只需全量包加最新差异包,差异备份占用的空间逐渐增大,但恢复速度更快,选择哪种取决于你对恢复时间(RTO)的要求,恢复窗口敏感就选差异备份。
自动化备份的核心价值不是“跑了脚本”,而是“每次都能恢复”,花半小时把脚本和计划任务配好,未来能省下无数个手忙脚乱通宵救数据的夜晚。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/659311.html





