今天聊一聊如何做好一个网站的备份工作,我会循序渐进的聊透这个问题。
本文以我的博客网站备份为案例讲解。先从手动备份聊起,在循序渐进优化和补充细节,编写脚本,使用定时任务,使用rsync增量备份,md5变更校验,发送邮件通知等。除了讲demo,还会深入讲解命令的配置项,原理等
为什么要网站备份?
网站备份是一样安全防御措施,是未雨绸缪的工作,以应对一些极端场景下的灾难,把损失降到最低。无论是个人网站还是企业网站,备份的作用都是不言而喻的。
手动备份
补充知识点:关于备份所需linux基础命令如cp、scp、tar、 grep可以读一下我的另一篇文章《超全的linux基础总结》
备份目标:vanblog的数据库、图床、nginx配置和服务器配置/etc目录
vanblog是一款开源软件,我的博客就是使用这款开源软件搭建的,目前服务器是在腾讯云上买的,考虑到以后有服务器迁移的计划以及保证数据不被丢失,所以需要定期备份。但是关于vanblog大家不用了解太多,我是采用docker的方式启动的,通过docker容器卷映射,我会告知备份哪些目录即可。
只要知道我要备份的目录如下即可
/home/ubuntu/myDockerFiles/vanblog/data/mongo/vanBlog vanBlog数据库备份
/home/ubuntu/myDockerFiles/vanblog/data/static vanBlog 静态资源备份
/etc/ 服务器配置备份
/home/ubuntu/myDockerFiles/nginx2 备份nginx
我在/tmp文件夹下创建backup文件夹存放着三个目录的压缩文件 执行的脚本如下
shmkdir -p /tmp/backup/
tar zcf /tmp/backup/$(date +%F_%H:%M)_mongo_vanblog.tar.gz /home/ubuntu/myDockerFiles/vanblog/data/mongo/vanBlog
tar zcf /tmp/backup/$(date +%F_%H:%M)_vanblog.tar.gz /home/ubuntu/myDockerFiles/vanblog/data/static
tar zcf /tmp/backup/$(date +%F_%H:%M)_etc.tar.gz /etc
tar zcf /tmp/backup/$(date +%F_%H:%M)_nginx2.tar.gz /home/ubuntu/myDockerFiles/nginx2
# 本地电脑执行scp下载文件夹
scp -P myport ubuntu@my-ip:/tmp/backup ./
rsync 增量备份
上述手动备份的缺点是 要手动执行脚本,要自己记得定期备份,由于是全量备份耗时长。
这种方式个人网站备份或许还行,但对于企业来说不现实。
好在linux有一个工具rsync, 它和scp命令一样好用,但它是增量备份,
示例命令:rsync -avz /etc/ root@backup_ip:/tmp/
第一次执行全量下载/etc目录, 第二次执行,下载/etc目录新增和有变更的内容
下面了解下rsync
rsync的应用场景
作为命令使用, 临时拉去、推送数据。 (也可以用scp实现)
定时备份:rsync服务+定时任务
实时同步:rsync服务+sersync/lsyncd实现实时同步,解决存储服务单点问题
rsync服务于异地容灾(找一个异地的服务器存放备份)
使用示例:把 /etc/目录传输到备份服务器的/tmp目录。
scp -r /etc/ root@backup_ip:/tmp/
rsync -avz /etc/ root@backup_ip:/tmp/
与scp功能类似rsync
可以将当前机器的文件资源上传到备份机上(推)
也可以从备份机下载文件资源到当前机器(拉)
rsync使用rsync -a源文件目标推送:rsync/etc/hostnameroot@10.0.0.31:/tmp拉取:rsyncroot@/10.0.0.31:/etc/hosts/opt/
rsync实现自动备份
前面备份执行的命令我们可以写个在脚本里,这样一键执行,但是rsync的远程模式是需要交互的,输入命令后还需要手动输入ssh密码才可以执行。
我们希望跳过输入密码的阶段, rsync有个选项--password-file,然而折腾下来无法实现预期效果。
原因是rsync对于自动脚本执行有严格的安全控制,一般企业都有专门的备份服务器,在备份服务器上搭建rsync服务端,在网站服务器上配置定时任务执行脚本来把数据增量备份到备份服务器上。
其实rsync有三种使用模式
本地模式 类似cp
远程模式 类似scp
rsync守护进程模式
这里就是使用rsync的守护进程模式
以Ubuntu为例,我参考按照油管视频Ubuntu 18配置rsync,当然也有坑的,我用红色文字描述。
安装ubuntu自带rsync,这一步跳过
开启服务 sudo vi /etc/default/rsync
设置RSYNC_ENABLE=inetd
创建配置文件/etc/rsyncd.conf,从/usr/share/doc/rsync/examples/rsyncd.conf模版复制一份,按照视频是先配置不开启账号密码效验的版本,我偷个懒跳过,直接上完整版本
sh[ftp] # 模块名字 用户客户访问服务端的时候指定
comment = www by guoguo # 注释署名名
path = /home/backup # 模块对应的路径,建议和模块名一致
use chroot = yes
lock file = /var/lock/rsyncd # 进程/服务的锁文件 防止重复运行
read only = no # no表示可以进行读写
list = yes
uid = root
gid = root
auth users =rsync # rsync服务端进行验证用户:用户名
secrets file = /etc/rsyncd.secrets # rsync 服务端进行验证:密码文件
strict modes = yes
ignore errors = no
ignore nonreadable = yes
transfer logging = no
timeout = 600
refuse options = checksum dry-run
dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz
注这里跳过了注释cat /etc/rsyncd.conf |grep -v "^#"
这里看一下 /home/test目录和/etc/rsyncd.secrets文件的权限
/home/test目录和/etc/rsyncd.secrets文件 的所有者都是root 对应配置文件的uid和 gid配置项, 你可以使用chown修改文件的所有者
/home/test目录的权限是755,/etc/rsyncd.secrets文件的权限是600,可使用 chmod修改文件权限
/etc/rsyncd.secrets文件内容为rsync:pwd
测试 在另一台机器也就是rsync客户端,创建文件/etc/rsync.client内容为pwd,与服务端/etc/rsyncd.secrets文件内容对应上,文件所有者和权限如下
配置好了要重新rsync服务 /etc/init.d/rsync restart 或者 systemctl start rsync,
检查rsync 有没有启动 lsof -i:873 或者 systemctl status rsync
配置开机自启动 systemctl enable rsync
因为后面要配置定时任务,定时任务一般都是root账户执行,所以这里使用root账户,执行命令也是root账户,具体命令rsync -vzrtopg --progress --password-file=/etc/rsync.client rsync@yourip::ftp .
我解释下rsync@yourip::ftp这段内容
rsync 与服务端配置文件的auth users字段对应上
:: 固定格式
ftp 与服务端配置文件[]中的内容对应上,表示一个模块
最后一个点表示当前目录,即下载到当前目录
如果前面的操作无误,这个命令可以将服务器 当前目录 增量同步到 备份服务器的/home/backup目录。
下面来看一下实际案例,我用要备份4个文件夹
/home/ubuntu/myDockerFiles/vanblog/data/mongo/vanBlog
/home/ubuntu/myDockerFiles/vanblog/data/static
/etc
/home/ubuntu/myDockerFiles/nginx2
完整/etc/rsyncd.conf的配置如下
sh[etc]
comment = public archive
path = /home/backup/etc
use chroot = yes
lock file = /var/lock/rsyncd
read only = no
list = yes
uid = root
gid = root
auth users =rsync
secrets file = /etc/rsyncd.secrets
strict modes = yes
ignore errors = no
ignore nonreadable = yes
transfer logging = no
timeout = 600
refuse options = checksum dry-run
dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz
[mongo_vanblog]
comment = www by guoguo
path = /home/backup/mongo_vanblog
use chroot = yes
lock file = /var/lock/rsyncd
read only = no
list = yes
uid = root
gid = root
auth users =rsync
secrets file = /etc/rsyncd.secrets
strict modes = yes
ignore errors = no
ignore nonreadable = yes
transfer logging = no
timeout = 600
[vanblog]
comment = www by guoguo
path = /home/backup/vanblog
use chroot = yes
lock file = /var/lock/rsyncd
read only = no
list = yes
uid = root
gid = root
auth users =rsync
secrets file = /etc/rsyncd.secrets
strict modes = yes
ignore errors = no
ignore nonreadable = yes
transfer logging = no
timeout = 600
[nginx2]
comment = www by guoguo
path = /home/backup/nginx2
use chroot = yes
lock file = /var/lock/rsyncd
read only = no
list = yes
uid = root
gid = root
auth users =rsync
secrets file = /etc/rsyncd.secrets
strict modes = yes
ignore errors = no
ignore nonreadable = yes
transfer logging = no
timeout = 600
/etc/backup.sh 网站服务器
rsync -vzrtopg --progress --password-file=/etc/rsync.client /etc/ rsync@backup-ip::etc
rsync -vzrtopg --progress --password-file=/etc/rsync.client /home/ubuntu/myDockerFiles/vanblog/data/mongo/vanBlog/ rsync@backup-ip::mongo_vanblog
rsync -vzrtopg --progress --password-file=/etc/rsync.client /home/ubuntu/myDockerFiles/vanblog/data/static/ rsync@backup-ip::vanblog
rsync -vzrtopg --progress --password-file=/etc/rsync.client /home/ubuntu/myDockerFiles/nginx2/ rsync@backup-ip::nginx2
网站服务器 执行crontab -e 增加内容
sh00 02 * * * bash /etc/script/backup.sh &> /dev/null
每天凌晨2点自动增量备份
温馨提示: rsync同步文件是只改只增,不删,如果你要考虑同步删除,可以使用NFS,但是NFS 是实时同步的。
rsync 知识点补充(可跳过)
业务需求总是千变万化的,补充在写rsync的知识点备用
rsync命令的配置项
rsync 的选项
指定端口 -e 'ssh -p port'
-a 是 -rlptgoD的简写
-r递归复制
-l复制软连接
-p 保持权限不变
-m 保持修改时间不变
-o 用户组不变
-D --deices --specials 设备于特殊文件
-v展示过程 通过这个可以观察到rsync是增量更新
-z 传输数据的时候进行压缩(推荐公网用)
-P 断电续传
--bwlimit 限速
--exclude --exclude-from 排除
注意
rsync对于目录/etc/ 和 /etc是有区别的
/etc /etc目录+目录下的内容
/etc/ /etc/目录下的内容
rsync 还有一个选项--delete,保持源与目标数据一致,比较危险,一般实时同步才会使用,使用前慎重
rsync 还有两个选项用于安全控制的
hosts allow = 10.0.0.0/24 # 只允许哪些ip或网段访问的白名单,多个网段用“,”拼接
hosts deny = 0.0.0.0/32 # 黑名单
由于rsync的加密机制比较弱,建议在不要在公网使用,而是在局域网内使用,密码也要设计复杂一点
失败的案例
最初我是看的老男孩的教程,那个课程是基于Centos的,昙花一现的好过,后来又不行了,这里粘贴一下笔记
部署 ubuntu系统已经自动安装,Centos可以用yum安装一下yum install -y rsync
新建配置文件/etc/rsyncd.conf,内容如下
sh# 全局配置
fake super =yes # centos7 hack 如果不开启则传输报错(伪装成root用户)
uid = rsync
gid = rsync
use chroot = no
max connections = 100
timeout = 600
lock file = /var/log/rsyncd.lock # 进程/服务的锁文件 防止重复运行
pid file = /var/run/rsyncd.pid #存放服务的pid号
log file = /var/log/rsyncd.log # 服务端日志
ignore errors #忽略错误
# hosts allow = 10.0.0.0/24 # 只允许哪些ip或网段访问 白名单
# hosts deny = 0.0.0.0/32
#############
[data_rsync] # 模块名字 用户客户访问服务端的时候指定
comment = www by guoguo # 注释署名名
path = /data_rsync # 模块对应的路径
read only = no # no #可以进行读写
list = no # 关闭rsync服务端列表功能
auth users = rsync_backup # rsync 服务端进行验证用户:用户名
secrets file = /etc/rsync.password # rsync 服务端进行验证:密码文件
别着急启动,要创建 用户、目录、密码文件
shuseradd -s /sbin/nologin -M rsync # 添加rsync虚拟用户
echo 'rsync_back:1' > /etc/rsync.password # rsync_back是用户名 密码是1
chmod 600 /etc/rsync.password # 权限一定要改,不然rsync服务认为是故障
mkdir -p /data_rsync/
chown -R rsync.rsync /data_rsync/
启动服务并配置开启自启动
启动服务端 systemctl start rsyncd
开机启动 systemctl enable rsyncd
我的服务器是Ubuntu系统,运行结果是失败的
通过搜索引擎和chatGPT找到的解决方案是
修改/etc/default/rsync文件
创建文件/etc/systemd/system/rsyncd.service内容如下
sh[Unit]
Description=fast remote file copy program daemon
After=network.target
[Service]
ExecStart=/usr/bin/rsync --daemon --no-detach
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
User=rsync
Group=rsync
[Install]
WantedBy=multi-user.target
另外rsync服务使用的是873端口,记得去防火墙放行873端口。
再次尝试启动服务和配置开启自启动OK了。
检测配置变更
完整的备份流程还记录下哪些变更,然后发送邮件。
检测变更可以使用命令md5sum
md5sum用于计算一个文件的hash值
shroot@myServer:/tmp# echo bbb > bb.txt
root@myServer:/tmp# md5sum bb.txt
b8694d827c0f13f22ed3bc610c19ec15 bb.txt
root@myServer:/tmp# md5sum bb.txt > comp.txt
root@myServer:/tmp# cat comp.txt
b8694d827c0f13f22ed3bc610c19ec15 bb.txt
root@myServer:/tmp# md5sum -c comp.txt
bb.txt: OK
root@myServer:/tmp# echo ccc > bb.txt
root@myServer:/tmp# md5sum -c comp.txt
bb.txt: FAILED
md5sum: WARNING: 1 computed checksum did NOT match
root@myServer:/tmp#
一般情况下都是打个压缩包 比较文件,这样能检测出来有没有配置变更。
如果一定要检测文件夹变更,可参考下面的示例
shroot@myServer:/tmp# md5sum `find /etc -maxdepth 1 -type f` > md5sums.txt
root@myServer:/tmp# md5sum -c md5sums.txt | grep -v "OK$"
root@myServer:/tmp# echo aa >> /etc/test.txt
root@myServer:/tmp# md5sum -c md5sums.txt | grep -v "OK$"
/etc/test.txt: FAILED
md5sum: WARNING: 1 computed checksum did NOT match
root@myServer:/tmp# md5sum -c md5sums.txt | grep "FAILED$"
md5sum: WARNING: 1 computed checksum did NOT match
/etc/test.txt: FAILED
root@myServer:/tmp#
这个命令可以检查文件夹下面的修改的配置,无法检测新增的配置, 如果想要检测新增的配置有以下几个方案
对目录压缩,在计算md5 hash 然后比较
diff 或 vimdiff
shmd5sum `find /etc -maxdepth 1 -type f` > md5sums2.txt
diff md5sums2.txt md5sums.txt
发送邮件
思路是这样,在脚本中 把输出结果写入到一个文件中,示例
shmd5sum -c md5sums.txt | grep "FAILED$" &> /tmp/result.txt`
通过mail命令发送邮件
shcat /tmp/result.txt | mail -s "`date +%F__%H:%M` 备份日志" 2315162186@qq.com
但是这种无邮箱地址的邮件会被送到垃圾箱
需要配置邮件发送人,可以参考 我之前写的文章 发送邮件
至此,这算是较为完整的网站备份流程了。