本文封面背景图采用CC-BY-SA-4.0协议,来源于Wikipedia
前言
本文主要讨论Linux下的数据备份方式
rsync
rsync是一个远程数据同步工具,可通过ssh或rsh传输数据,支持匿名传输,速度快,安全性高。
- 可按文件大小、时间等进行过滤
- 可使用
include和exclude文件进行过滤 - 可使用
--delete参数删除目标端没有的文件 - 可使用
--link-dest参数创建硬链接 - 可使用
--bwlimit参数限制带宽 - 可使用
--progress参数显示进度 - 可使用
--dry-run参数模拟运行 - 可使用
--log-file参数记录日志 - 可使用
--password-file参数指定密码文件 - 可使用
--exclude-from参数指定排除文件 - 可使用
--include-from参数指定包含文件 - 可使用
--files-from参数指定文件列表 - 可使用
--exclude参数排除文件 - 可使用
--include参数包含文件 - 可使用
--max-size参数指定最大文件大小 - 可使用
--min-size参数指定最小文件大小 - 可使用
--max-delete参数指定最大删除文件数 - 可使用
--partial参数保留部分文件 - 可使用
--partial-dir参数指定部分文件目录 - 可使用
--timeout参数指定超时时间 - 可使用
--contimeout参数指定连接超时时间 - 可使用
--daemon参数启动守护进程 - 可使用
--address参数指定守护进程监听地址 - 可使用
--port参数指定守护进程监听端口 - 可使用
--config参数指定配置文件 - 可使用
--blocking-io参数指定阻塞IO - 可使用
--no-blocking-io参数指定非阻塞IO - 可使用
--stats参数显示统计信息 - 可使用
--progress参数显示进度 - 可使用
--no-motd参数禁用MOTD - 可使用
--no-detach参数禁用守护进程 - 可使用
--no-inc-recursive参数
笔者的主要需求是将内容备份到本地的机械硬盘中,所以使用rsync的命令如下:
sudo rsync -aAXHv --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/boot/efi/*" "/efi/*"} / /XXX/目标目录 --delete
其中的-aAXHv是rsync的常用参数,表示归档模式、保留ACL、保留扩展属性、保留硬链接、显示进度。
由于笔者使用的是btrfs,有时候想要备份单个子卷,可以使用--one-file-system参数或者-x参数,表示不跨越文件系统边界:
sudo rsync -aAXHvx / /XXX/目标目录 --delete
这里的-x参数表示不跨越文件系统边界,这样备份的就只有根目录所在子卷的内容。
tar
tar是一个归档工具,可以将多个文件或目录打包成一个文件,也可以将一个文件解包成多个文件或目录,支持压缩,但是不支持增量备份。tar还支持设置压缩参数,支持不同的压缩算法:
z:使用gzip压缩j:使用bzip2压缩J:使用xz压缩--lzma:使用lzma压缩--lzip:使用lzip压缩--lzop:使用lzop压缩--zstd:使用zstd压缩-a:根据文件拓展名自动选择压缩算法
笔者的主要需求是将内容备份到本地的机械硬盘中,所以使用tar的命令如下:
sudo tar -cavpf /XXX/目标目录/backup.tar --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/boot/efi/*" "/efi/*"} /
同理,如果想要备份单个子卷,可以使用--one-file-system参数,表示不跨越文件系统边界:
sudo tar -cavpf --one-file-system /XXX/目标目录/backup.tar /
dd和squashfs
dd是一个磁盘拷贝工具,可以将一个磁盘的内容拷贝到另一个磁盘,也可以将一个磁盘的内容拷贝到一个文件,也可以将一个文件拷贝到一个磁盘,也可以将一个文件拷贝到另一个文件,不支持增量备份。dd的优点是可以完整备份整个硬盘设备,缺点是备份的文件很大,会拷贝原有硬盘中没有数据的部分,而且不能压缩,占用较多的空间。因此,笔者一般会推荐在使用dd备份时,使用squashfs压缩,这样可以节省空间。
squashfs是一个只读压缩文件系统,它支持保留Linux权限及xattr拓展权限,可以调节块大小,保证随机访问性能,对压缩的支持也非常丰富,可以选择不同的压缩算法及压缩率。在一般场景中,笔者推荐使用zstd:3的压缩算法,这样可以节省空间,而且压缩速度快、CPU占用很小。与tar.zst等基于tar的压缩备份方案相比,squashfs最大的优势在于可以直接挂载使用,而不需要解压缩,这样可以节省大量的时间;另外,squashfs还支持文件级别重复数据删除,进一步节省空间。
文件/目录级备份
如果需要备份已经挂载的文件系统上的文件,可以直接使用mksquashfs,例如:
# 备份 /home 目录
sudo mksquashfs /home /XXX/目标目录/backup.squashfs -comp zstd -Xcompression-level 3 -b 1M
# 备份 / 目录
sudo mksquashfs / /XXX/目标目录/backup.squashfs -comp zstd -Xcompression-level 3 -b 1M -e /dev -e /proc -e /sys -e /tmp -e /run -e /mnt -e /media -e /lost+found -e /boot/efi -e /efi
# 备份 / 子卷
sudo mksquashfs / /XXX/目标目录/backup.squashfs -comp zstd -Xcompression-level 3 -b 1M --one-file-system
这样创建的squashfs是一个直接包含备份文件的文件系统,可以直接挂载使用。
块设备级备份
有时候我们可能需要备份某些在Linux下不方便直接挂载并备份的分区,比如受BitLocker加密的NTFS分区等,这时,为了完成保留整个硬盘设备的信息,我们可以直接备份整个硬盘设备。如果需要备份整个硬盘设备,可以使用dd和mksquashfs结合,即,用mksquashfs调用dd的输入流,例如:
sudo mksquashfs - /XXX/目标目录/backup.squashfs -p "backup.img f 0644 root root dd if=/dev/nvme0n1 bs=1M" -p "/ d 0755 0 0" -comp zstd -Xcompression-level 3 -b 1M
这里的-表示标准输入流,-p表示添加文件,-p后面的内容是mksquashfs的文件描述符,f表示类型为文件,后面紧跟的是权限信息,dd if=/dev/nvme0n1 bs=1M表示调用dd的输入流,if=/dev/nvme0n1表示输入文件,bs=1M表示块大小;/表示根目录,d表示类型为目录,后面同样跟有权限信息。
整体上,这个命令的意思是,将/dev/nvme0n1的内容作为输入流,作为backup.img文件的内容,将backup.img文件放在创建的squashfs文件系统的根目录,然后压缩成squashfs文件系统。这样既保留了整个硬盘的完整存储信息,又启用压缩,节省了空间。不过,从这样的备份中读取内容时,需要先挂载squashfs文件系统,然后加载其中的backup.img文件为loop设备,再挂载所需要挂载的分区。
btrfs send
由于笔者使用的是btrfs,除了以上较为通用的方法外,还可以使用btrfs的send和receive命令进行增量备份。send命令可以将一个子卷的内容发送到一个文件中,receive命令可以将一个文件中的内容接收到一个子卷中。send命令支持增量备份,可以将两个子卷之间的差异部分发送到一个文件中,receive命令也支持增量备份,可以将一个文件中的差异部分接收到一个子卷中。
btrfs send只能发送只读的btrfs子卷,我们需要首先创建当前子卷的只读快照,例如:
sudo btrfs subvolume snapshot -r / /XXX/snapshots/@-ro
然后即可使用btrfs send命令将快照发送到另一个btrfs文件系统中,例如:
sudo btrfs send /XXX/snapshots/@-ro | sudo btrfs receive /XXX/目标目录
增量备份与之类似,只需要在send命令中添加-p参数,例如:
sudo btrfs send -p /XXX/snapshots/@-ro /XXX/snapshots/@-ro-new | sudo btrfs receive /XXX/目标目录
btrfs receive所新建的子卷也是只读的,如果需要使用,需要对其创建可读写的快照,例如:
sudo btrfs subvolume snapshot /XXX/目标目录/@-ro /XXX/目标目录/@-rw