shell定时自动备份网站文件
Contents
起因
网站文件是典型的“改着改着就没了”的数据:发个新版本、上传个附件、改个配置,谁也说不准哪次操作就把东西弄丢;再碰上磁盘坏道或误删,没有备份就只能重来。手工 tar 一次两次坚持得下来,长期可靠的做法只有一条:交给定时任务,让机器每天自己做。
需求
定时备份网站/home/www/htdocs/blog到/home/www/backup/site-blog下,
并删除10天前的备份。
技术实现原理
整体思路:全量打包 + 时间戳文件名 + 按天数清理
一条因果链串起整个脚本:备份要能独立恢复,所以每次做完整打包——一个 tar.gz 就是一个完整快照,任何一个都能单独拿来还原;备份不能无限占盘,所以文件名带时间戳、再按保留天数清掉过期文件;要无人值守,所以整套逻辑交给 crontab 每天定点触发。
为什么要用 -X 排除目录
网站的 runtime、logs 这类目录是运行时产物:每次访问都在变、体积大、而且随时可以重新生成。把它们打进备份有三个坏处——体积暴涨、打包变慢、tar 读到正在变化的文件还会报 “file changed as we read”。用 -X 把它们从打包清单里剔掉,备份里剩下的就是“丢了真找不回来”的部分。
find -mtime 的清理逻辑
三个过滤条件各管一道闸:-name "$WEBSITE_PREFIX*" 按前缀匹配,只删本脚本自己产生的备份,目录里放的其他文件绝不误伤;-mtime +10 按“文件修改时间超过 10 天”筛选;-exec rm {} \; 把筛选结果逐个删掉。注意 -mtime 是按 24 小时取整的:+10 匹配到的是第 11 天及更早的文件,保留期要卡得准就得记住这个边界。
为什么逻辑写在脚本里而不是直接塞进 crontab
crontab 的命令行里 % 是特殊字符——会被解释成换行、后面的内容被当成标准输入,date +%Y%m%d 这类表达式直接写进 crontab 十有八九出错。把逻辑装进脚本、crontab 只留一行调用,既绕开这个坑,也方便单独测试:手动跑一遍脚本就能验证备份结果,不用等第二天凌晨。
创建脚本
|
|
脚本内容
|
|
脚本说明
- 变量全部集中在文件头:目录、保留天数、前缀想改只动一处;
DATE=\date +%Y%m%d-%H%M%S``:文件名带精确到秒的时间戳,一天跑多次也不重名,恢复时一眼看出是哪刻的快照;tar zcvf ... -X exclude.txt:c 建包、z 过 gzip 压缩、v 打印打包过程、f 指定输出文件;-X 跟一个排除清单文件,一行写一个要剔除的路径;- 开头的
mkdir -p:备份目录可能还没建,-p 会连父目录一起创建,且目录已存在时不报错; - 清理那行 find 的三个条件见上文原理。
设置执行权限
|
|
设置定时任务
crontab -e
文件内容:
|
|
五个字段从左到右是 分 时 日 月 周,3 4 * * * 即每天 04:03 执行。
每天凌晨4:03分开始执行备份任务。挑 4:03 而不是整点 4:00 是个运维小惯例:整点是定时任务扎堆的时刻(日志轮转、别的备份都在整点跑),错开几分钟能少抢一次磁盘和 CPU。
踩坑记录与注意事项
- % 在 crontab 里是特殊字符:直接把
date +%Y%m%d写进 crontab 会被截断(% 后内容被当作标准输入),日期逻辑放脚本里(本文做法)或把 % 转义成 %; - cron 的环境是精简的:PATH 往往只有 /usr/bin:/bin,脚本用到非标准路径的工具时(如 /usr/local/bin 下的程序)写绝对路径最稳;
- -mtime +10 的边界:匹配的是第 11 天及更早的文件,保留期要卡准就得按这个取整规则算;
- 备份目录和网站同盘:本文 /home/www/backup 与站点在同一块盘,盘一坏两边一起没。真正的容灾要再把备份推到另一台机器/另一块盘(本站另有一篇 rsync+VPS 的方案干这件事);
- tar 打到正在写的文件会告警:“file changed as we read” 就是备份瞬间文件还在变,用 -X 排除运行时目录既是减体积也是避开它;
- 加上日志重定向好排查:crontab 里可写成
... >> /home/www/backup/site-blog.log 2>&1,出问题翻日志,不用干等邮件; - 恢复时注意路径:tar 打包给的是绝对路径,默认会去掉开头的 /(提示 “Removing leading
/' ...”),解出来是相对路径结构,恢复要cd /` 再解压才能还原到原位。
Author 软件开发大郭
LastMod 2022-01-06