引子
为啥子要备份捏?
- 作为Arch用户,一旦系统出现问题,可以立即恢复
- 作为Arch用户,配置高度定制化系统耗时长
- 因为特殊原因,我在使用SMR硬盘,挂掉概率高
- 即使电脑丢失/被黑/
爆炸,也能保障数据 - 可以在其它设备上迅速克隆出来一个一模一样的系统
- 我想备份我的服务器
- 预防地震、火灾等不可抗因素
- ······
备份方案
以下是我使用到的一些备份软件、硬件等
- dm-crypt 数据加密
- rsync 备份数据
- btrfs 文件系统
- 1T 旧硬盘用于本地备份
- 1T rsync服务器用于异地备份
- 代理服务器 用于加速传输
- ······
PS:我的/目录是Ext4文件系统,所以采用rsync+btrfs。如果你的/目录本身就是btrfs,这篇文章不一定适合你。
特性
我这套备份方案的优缺点如下:
优点
- 良好的数据加密
- 全系统备份
- 增量备份
- 增量同步到服务器
- 同步时支持断点续传
- 支持异地备份(可选)
- 快速创建/删除备份
- 文件压缩
- 支持备份文件只读(借助子卷)
- ······
缺点
以下缺点均是为异地备份做出的妥协:
- 传输过程不能使用TLS
- ssh传输性能低
- 稀疏文件使写入性能下降
- 扩容时可能导致备份损坏
- 你需要花钱买一个大硬盘服务器或者对象存储
阅读方法
- 红色内容代表警告,你应该仔细查看警告内容!否则可能损毁系统!!!
- 橙色内容代表注意,你应该留心橙色内容,以正确使用!!
- 蓝色代表提醒,以突出显示较重要内容!
- 黑色为一般文字。
警告:你不能直接无脑copy任意一条命令,运行命令前请先动脑子!想清楚了再执行!
参考及要求
参考链接
备份这个东西,每个人的需求可能不一样,有的人只需要使用网盘备份文件,而有的人需要复杂的备份系统。我把一些参考链接放在这里,如果你不喜欢我的方法,你也可以定制自己的备份方法。除此之外你需要英语阅读能力。
- rsync+btrfs+dm-crypt 备份整个系统
- 用btrfs来做备份盘
- Btrfs: Subvolumes and snapshots
- Do-It-Yourself Backup System Using Rsync and Btrfs
- 扫盲 dm-crypt——多功能 Linux 磁盘加密工具(兼容 TrueCrypt 和 VeraCrypt)(建议使用tor网络)
- Backup and Restore Your Linux System with rsync(YouTube视频)
上面的链接是几个比较有用的,你还需要自己搜索内容。rsync/btrfs分区/dm-crypt都是强大的工具,可能需要一段时间理解。
要求
Arch用户- 英语阅读能力
- 了解btrfs的子卷、snapshot含义
- dm-crypt基本使用方法
- rsync基本使用方法
- 熟悉Linux基本命令
我以后可能会写相关博文
格式化硬盘
由于我需要异地备份,网上目前没有相关教程,而btrfs压根不支持异地备份,令人头大。所以我的硬盘采用:
Ext4作为底层文件系统,在其上建立一个虚拟加密卷,并格式化成btrfs。(禁止套娃)
虚拟加密盘需要把内容储存到一个文件里,我们可以创建一个文件,文件的大小决定了虚拟加密盘的大小。这样我只需要备份虚拟加密卷就完事了。下面,你需要先把移动硬盘连接到电脑上。
警告:如果你不需要异地备份,你应该用luks模式直接加密整个移动硬盘,而不是采用下方的虚拟卷方式!
注意:创建的稀疏文件大小还应该考虑你的同步工具是什么,你应该了解你的同步工具在实现增量更新的时候是否会rewrite原文件,如果需要rewrite,那么服务器可利用空间为最大剩余容量的50%,rsync具有-inplace选项以取消rewrite(你也可以将文件拆分,提升利用率)。
注意:(不使用rsync做异地备份请忽略)即使rsync的-P选项可以处理稀疏文件,但是它依旧极其占用CPU、内存、网络,且工作不正常。对于本文的来说,稀疏文件应该尽可能接近当前系统体积。如果你是高阶用户,或者备份整个服务器系统,你应该根据实际情况调整大小.。
lsblk #查看你的硬盘以及分区状况
#如果你还没有分区或者有不用的分区,你需要使用cgdisk/cfdisk等建立分区
#以下以sdb1作为移动硬盘分区
sudo mkfs.ext4 /dev/sdb1 #将sdb1格式化成ext4文件系统
mkdir /mnt/d1
mkdir /mnt/d2
sudo mount /dev/sdb1 /mnt/d1 #挂载/dev/sdb1到/mnt/d1
sudo chmod 777 /mnt/d1 #改变目录权限,让非root用户能够读写移动硬盘
truncate -s 30G /mnt/d1/backup.iso #瞬间创建一个30G的空洞文件,可以以其它后缀名结尾,比如vol、img等
cryptsetup --cipher aes-xts-plain64 --key-size 512 --hash sha512 --iter-time 10000 luksFormat /mnt/d1/backup.iso #根据引导完成创建
sudo cryptsetup luksOpen /mnt/d1/backup.iso backup #打开虚拟加密卷
sudo mkfs.btrfs /dev/mapper/backup #把虚拟加密卷格式化为btrfs文件系统
sudo mount /dev/mapper/backup /mnt/d2 #把虚拟加密卷挂载到/mnt/d2
sudo chmod 777 /mnt/d2
df -hT #查看当前挂载情况
通过以上命令:
- 把你的移动硬盘格式化成了Ext4文件系统
- 将硬盘挂载到了/mnt/d1
- 使用dm-crypt在硬盘上创建了一个虚拟加密卷
- 将虚拟加密卷并格式化成Btrfs
- 将虚拟加密卷挂载到了/mnt/d2
你还可以使用验证文件来代替密码
稀疏文件实际大小
关于稀疏文件在Linux系统的储存方式,这里我就不多说了,如果你想深入了解,你可以看看
我们先前使用了truncate创建的是30G的稀疏文件backup.iso。但是,实际上它占用的空间并不是30G,你可以使用下列命令查看相关信息。
du -h --apparent-size /mnt/d1/backup.iso #查看最大大小
du -h file.img #查看实际占用
弹出硬盘
这里插播一下弹出硬盘的方法
sudo umount /mnt/d2
sudo cryptsetup luksClose backup
sudo umount /mnt/d1
如果出现无法卸载的情况,关闭文件管理等应用,重新打开终端,输入sync命令,把缓冲区文件写入磁盘。
输入上述命令后,点击系统托盘里那个移除设备的小三角(部分系统要点两次,第一次是挂载,第二次是弹出)或者输入下面这个命令。
sudo udisksctl power-off --block-device /dev/sdb
这么做是为了使机械硬盘停转,磁头复位,主动防止磁头刮伤盘面。对应SSD/U盘的话就是使主控断电,延长使用寿命。
如果你使用3.5寸硬盘/外置供电,你可以在输完命令后直接断开USB数据线,硬盘停转后,关闭电源。
备份策略
啥?你刚刚试了把硬盘弹出?没关系,再试一遍挂载过程。
如果你要理解下面的内容,需要先搞清楚btrfs文件系统的工作方法。
现在有两种备份策略,我们先cd到当前btrfs文件系统所在的路径,对于本文是/mnt/d2
单一卷
PS:这名字是我取的,其实也不能这么叫,但是也没确切的说法
将所有文件使用rsync备份到根卷的同一目录下,然后直接创建snapshot子卷,目录树像这样
/mnt/d2(rootvol,dir, rw)
├── bin(dir)
├── boot(dir)
├── home(dir)
├── ···
├── backup2020.1.1(subvol, snapshot, ro)
│ ├── bin
│ ├── boot
│ ├── home
│ └── ···
└── backupt2020.2.1(subvol, snapshot, ro)
├── bin
├── boot
├── home
└── ···
多目录
/mnt/d2(rootvol,dir, rw)
├── bin(dir)
│ ├current(rootvol, rw)
│ ├bin2020.1.1(subvol, snapshot, ro)
│ └bin2020.2.1(subvol, snapshot, ro)
├── boot(dir)
│ ├current(rootvol, rw)
│ ├boot2020.1.1(subvol, snapshot, ro)
│ └boot2020.2.1(subvol, snapshot, ro)
├── home(dir)
│ ├current(rootvol, rw)
│ ├home2020.1.1(subvol, snapshot, ro)
│ └home2020.2.1(subvol, snapshot, ro)
├── others(dir)
│ ├current(rootvol, rw)
│ ├others2020.1.1(subvol, snapshot, ro)
│ └others2020.2.1(subvol, snapshot, ro)
├── ···
选择方法
单一卷更加简单,备份、恢复更加方便。第二个目录分类更精细,可以轻松实现不同目录下不同频率/日期备份吗,区别管理。当然单一卷也可以实现不同日期备份,但是不直观。
PS:不管你使用哪种方法,均不会影响备份速度和稳定性!换句话说,两者性能相似。对于本文,我们选择第一种备份方案。
除此之外,你还可以使用多个加密卷,对不同目录区别加密来提高安全性。
开始备份
以下,我们使用rsync命令,将当前系统内容同步到btrfs分区(位于/mnt/d2)
sudo rsync -avAXP --stats --delete --dry-run --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/home/vince/[a-z]*","/home/vince/[A-Z]*"} / /mnt/d2/arch_bak
rsync的一大串命令,下面我们来解析一下:
- -a archive模式
- -A 添加ACL,选择性备份文件
- -v和-P 显示详细进度
- -stats 显示单个文件进度
- -X 保留扩展属性
- –delete 实现增量备份,再次备份时会在备份中删除已删除文件
- –dry-run 模拟运行
- –exclude 支持ACL名单,排除不需要的部分
上面的ACL名单里,排除了压根不用备份的目录以及挂载目录,防止备份进入死循环。我没有备份home目录下以英文字母开头的文件夹,但是备份了隐藏文件。你应该根据自己的需求,来写排除的部分。
最后的/表示系统根目录,也就是说全系统备份。/mnt/d2/arch_bak表示备份位置,也就是说我在btrfs根卷下建立了一个文件夹,名字叫arch_bak,免得一打开btrfs卷全是文件夹。这样,我还可以备份其它系统,方便管理。
在你模拟运行后,确定没问题了,删除–dry-run直接备份即可。
注意:在以后的备份过程中,你都应该加上–dry-run来模拟,看看rsync要删除哪些文件,一旦输错地址可以及时发现,避免损坏备份甚至摧毁系统(有点像dd)。
制作snapshot
snapshot理解成快照就好啦!就像拍照片一样,给你当前的btrfs分区拍个照,记录每个文件的样子。由于btrfs是Copy-on-write系统(前提是你没把默认打开的Copy-on-write功能关掉),所以我们可以瞬间创建出来一个快照。
btrfs的snapshot以子卷(subvolume)形式储存,snapshot默认不会备份子卷,所以当你有了一个快照的时候,不用担心下一个snapshot会包含前一个snapshot。
来自Archwiki的一句话:快照不是递归包含的,这意味着子卷内的子卷在快照里是空目录。
mkdir /mnt/d2/snapshots
mkdir /mnt/d2/snapshots/arch_snapshots
sudo btrfs subvolume snapshot -r /mnt/d2 /mnt/d2/snapshots/arch_snapshots/$(date +'%Y-%m-%d_%H-%M')
-r 表示创建一个只读快照。如果你想更改这个快照内容,你需要为只读快照再创建一个快照,就可以获得一个只读快照的可写入副本.
现在我们在/mnt/d2/snapshots/arch_snapshot目录下创建了一个以时间命名的快照。
PS:btrfs的快照是卷的概念,所以你不能为某一目录创建快照,而是直接为某个根卷或子卷创建。我们打开刚刚创建的快照,就会发现我们的快照里包含snapshots/arch_snapshot目录。如果你不想要这些空目录,那就把快照创建到一个子卷里(子卷嵌套)。对于本片文章,除非你是重度强迫症,否则完全没必要。
删除snapshot
我的习惯是保留3次快照。所以我需要删除过旧的快照。前面说过,snapshot以subvolume的形式存在,所以删除子卷即可。
sudo btrfs subvolume delete /mnt/d2/snapshots/arch_snapshot/subvol_name
#subvol_name是子卷名,对于本文,子卷名是日期_时间
sudo btrfs filesystem defragment /mnt/d2 #整理碎片
扩容btrfs卷
如果你没有使用虚拟加密卷,请忽略这一章节。
之前,我们创建了一个大小为30G的虚拟加密卷,并且格式化成了btrfs。如果我们的加密卷不够用了,现在我们要扩容加密卷。原理就是在原先文件的末尾增加数据,接着增大加密卷大小,最后扩展btrfs分区。
警告
- 以下操作过程可能会损坏你的备份,请提前做好措施!
- 请按照目录弹出硬盘部分关闭加密卷,只保留移动硬盘的挂载!
- 请仔细阅读以下内容!!!
过程中,如果出现了btrfs分区损坏,你可以看看Btrfsck页面和Manpage/btrfs-check页面
truncate -s 512G /mnt/d1/backup.iso
#把backup.iso扩容到512G,是扩容到,不是增加!
sudo cryptsetup luksOpen /mnt/d1/backup.iso backup
sudo cryptsetup resize /dev/mapper/backup
sudo btrfs check -p /dev/mapper/backup #校验分区是否受损
sudo btrfs filesystem resize max /dev/mapper/backup
sudo mount /dev/mapper/backup /mnt/d2
此时我们就能看到分区大小的变化啦!
上传备份到服务器
关于异地备份的一些想法:
本篇文章使用了传输前的加密,来保障数据安全,传输过程中使用ssh。如果你不想这么做,还想要异地备份,你可以试试使用VPN网络来实现流量加密,确保信息安全,在服务器端你可以直接加密一个分区,或创建一个虚拟加密卷用于存储。
采用什么方法上传就是仁者见仁,智者见智了,根据你的环境自主选择。对于在这里我依旧选择可操作程度较高的rsync。你也可以使用带有校验、差异同步功能的网盘(貌似免费的百度云挺香,反正备份下载次数少)、BT协议(借助bt工具,如resilio sync、syncing还可以轻松实现一中心多地多备份)等。甚至架设本地服务器(FTP/HTTP下载),让备份服务器主动下载。
注意:差异同步、增量同步是两个重要属性!应该优先选择支持这两个属性的工具,其次还应注意服务器允许存储的最大文件大小。
如果你想要使用网盘,你可以看看这个页面:Comparison of online backup services,所以百度云香极了!全部支持还免费,网络环境好,不限制上传?!缺点就是下载的时候。。。
本文采用rsync的方式,所以首先你得有一个rsync服务器,建议运行在DAEMON模式。其次如果你的网络不好,你可能需要一个代理服务器。为了服务器安全性,你至少需要更改ssh端口,并采用证书验证。下面是两个教程
在确保了服务器的安全性了之后我们开始对文件进行上传。先在假设有一个socks5代理监听在本地1080端口,我们需要用netcat(OpenBSD版本)实现ssh over socks5进行加速。如果你没有netcat,用包管理器安装一个!
PS:对于天朝用户,如果你的rsync服务器如果在国外,请考虑ssh加代理或者直接使用rsync的明文传输。我更倾向于前者。如果服务器性能足够而带宽不足,可以考虑添加-z选项来加快传输,上传下载均适用。
初次上传
rsync -avSP -o "ssh -i /path/to/private/key -p 22 -o 'ProxyCommand nc -X 5 -x 127.0.0.1:1080 %h %p'" /mnt/d1/backup.iso [email protected]:/home/rsync
当前使用了证书验证,并假设有个代理监听在1080端口,请根据实际情况修改部分内容
-S代表文件为稀疏文件,让rsync进行优化。然而我在实际使用过程中,它老老实实地上传了30个G???目前暂不清除原因,没有看到相关问题。你还可以在rsync后面加上-c参数,实现checksum。当然它计算的是md5,而且对于大文件比较耗时,我的小服务器是吃不消的
/(ㄒoㄒ)/~~。顿时感觉网盘更香了!!!
更新上传
rsync -avSP --append --inplace --partial -o "ssh -i /path/to/private/key -p 22 -o 'ProxyCommand nc -X 5 -x 127.0.0.1:1080 %h %p'" /mnt/d1/backup.iso [email protected]:/home/rsync
上面的–inplace 取消rewrite属性,–append 增量同步。关于为什么要这么做可以看看Copying large files with Rsync, and some misconceptions
断点续传
关于断点续传,我们之前的两个命令都含有-P参数,所以如果在上传的同时网络断开了,只需要重复输入一个一模一样的命令
恢复
说明
rsync属于文件级别备份,而非块级/原子级,它更灵活也更复杂,所以分成以下两种恢复过程。你应该有一个LiveCD的Linux U盘,任何发行版均可。然后开始按照下面的操作恢复系统。
首先找到你的备份硬盘,老样子,挂载它。如果你按照上面的方法进行了异地备份,则可以使用下面这个命令来下载备份。
rsync -avz -o "ssh -i /path/to/private/key -p 22 -o 'ProxyCommand nc -X 5 -x 127.0.0.1:1080 %h %p'" [email protected]:/home/rsync/backup.iso /mnt/d1
磁盘情况
以下内容,我们以
- /dev/sda为Live USB
- /dev/sdb为预恢复的磁盘
- /dev/sdc为我们的移动硬盘(储存着加密的备份文件)
- 虚拟加密卷挂载到/run/d1
UEFI系统(GTP)
- /dev/sdb1为UEFI分区,大小512MB
- /dev/sdb2为swap分区
- /dev/sdb3为Ext4(/目录)
如果你有其它分区,请自行分区、挂载!
传统启动(MBR)
本片文章只记录UEFI情况,对于传统启动,只是没了上述的/dev/sdb1(EFI分区)其它情况均相同
注意:如果你的系统是损坏了文件,你可以直接按照下面的操作恢复。如果磁盘的分区表损坏,磁盘压根不能用了或需要克隆一个系统,你应该先看下面的磁盘损毁/克隆系统。
系统文件损毁
挂载文件系统
sudo mount /dev/sdb3 /mnt
sudo mkdir /mnt/boot
sudo mount /dev/sdb1 /mnt/boot
sudo swapon /dev/sdb2
安装cryptsetup然后按照之前的方法打开加密卷,挂载到/run/d1,然后运行就完成了系统的恢复!
sudo rsync -avAXP --stats --delete --dry-run --exclude={"lost+found","snapshots"} /run/d1/arch_bak /mnt
如果你想用snapshots里的内容恢复,十分简单,修改一下rsync的读取目录和exclude内容就行。
磁盘损毁/克隆系统
使用工具分区
注意:对于UEFI,你应该使用cgdisk,否则你应该使用cfdisk分区。而且应该尽量保持分区同之前一致!
lsblk #查看磁盘
cgdisk /dev/sdb #使用cgdisk,重新分区
建立文件系统,并挂载
mkfs.vfat /dev/sdb1
mkswap /dev/sdb2
mkfs.ext4 /dev/sdb3
把/(就是要恢复的硬盘)挂载到/mnt,把UEFI分区挂载到/mnt/boot,使用swapon命令启用交换空间
sudo mount /dev/sdb3 /mnt
sudo mkdir /mnt/boot
sudo mount /dev/sdb1 /mnt/boot
sudo swapon /dev/sdb2
使用rsync恢复系统
一切准备基本就绪,按照上面的系统文件损毁部分使用rsync命令恢复系统文件。
重装GRUB
接着进入chroot。我们以arch系统为例,其它系统均类似。
PS:对于arch用户,使用arch-chroot,如果你的liveUSB不是arch(例如Ubuntu),你可以使用包管理器(例如apt)安装一个arch-install-scripts,然后就可以使用arch-chroot啦。其它发行版请查阅手动安装文档。
arch-chroot /mnt /bin/bash #使用chroot
pacman -S grub os-prober #安装grub和os-prober
#grub-install
#对于UEFI系统
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=grub --recheck
#对于MBR
grub-install --target=i386-pc /dev/sdb --recheck
#重新生成grub.cfg
grub-mkconfig -o /boot/grub/grub.cfg
好啦!你已经恢复了你的系统!
结束
原作者(Vince)的话:写文不易,为了知识共享我不限制转载、再创作等,请各位姥爷在转载和再创作时留个链接和原作者。同时希望你能严格遵守 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议。