本文封面背景图采用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