系统本地备份
使用rsync及borg进行系统备份
Linux上的备份软件非常多,而且大部分为免费或者开源的,具体可参考Arch Linux Wiki中的对比,或者restic项目所作的总结。如果不在乎GUI,推荐使用rsync或borg,可通过脚本配合systemd timer实现定时备份,并由inotify推送通知。
rsync是Linux上大名鼎鼎的同步工具,已有近25年历史,Linux系统一般已预装。常见的备份软件大多与其有关联:Back in Time、TimeShift 等是直接基于rsync实现;Dropbox、Duplicity 虽未直接使用rsync,也都使用了基于rsync算法的实现,Deja Dup 则是 Duplicity 的图形界面;rclone 宣称是针对商业云存储的rsync工具,足见rsync的影响力。
rsync支持基于数据块的增量式备份,也可以更新整个变动文件。增量式备份需要读取全部源及目标文件以实现对比,默认情况下本地备份时,会直接更新整个变动文件,而在网络备份时,则会采用增量式备份。而配合inotifywait监测目录变动,还可实现文件的实时同步。
rsync的缺点在于它是同步软件,并非针对文件备份的,缺少备份软件的一些常见特性:
- 只能保留最新版本,不能同时保持多个历史版本。
--backup-dir
,--link-dest
等可在一定程度上实现该功能,具体参考下面介绍。 - 不能自动加密备份文件。
而borg作为专门的备份软件,上述问题都能很好处理。borg属于备份软件中的后起之秀,始于2015年,作为更早的Attic(始于2010)的分支,现在发展的非常不错,在reddit等社区中有较高评价。
rsync
1 | 备份:rsync -avP --delete --exclude={.cache,.apps} ~/ /media/$USER/backup/rsync/ |
参数意义:
-a
--archive
存档模式:递归拷贝目录,保持文件权限、修改时间等元信息,保持符号链接及特殊文件等。-v
--verbose
冗长模式:输出同步过程的详细文件信息。-P
--process --partial
显示文件的复制进度,保留传输不完整的文件--include
设置包含名单--exclude
设置忽略名单--delete
删除目标端多余(同步源没有)的文件
注意事项:
- rsync默认基于文件大小及修改时间判断文件变动,通过参数
-c
可调整为基于checksum。 - 同步时如果遇到文件冲突,比如上次同步后两边各有不同的更新,rsync并不会有任何提示或针对性处理,默认始终为同步源覆盖同步目标,即使目标端文件修改的更晚。如果使用
-u
参数,则当目标端文件修改时间更晚时,不会进行覆盖,除此之外不会对冲突内容做更多处理。 - 参数
-b
(--backup
)可开启备份,为同步过程中被替换或删除的文件创建原始备份,默认文件备份与文件处于同一目录,文件名为原文件名后加~
。
--backup-dir=DIR
参数可为备份文件指定单独的存储备目录,备份文件将会存储于指定的目录下,并保持目录结构。其中DIR
可以使用绝对路径($HOME/delete
)或相对路径(../delete
)。需注意的是~
不会展开为home目录,而是被作为相对路径处理,$HOME
可以展开为home目录。
要实现类似记录历史版本的效果,可将DIR
设为 …/$(date --iso-8601=minutes),每次文件同步都会在目标目录旁创建以当前时间命名的更新备份,但要将某个文件恢复到某个历史版本只能手动操作了。
如果同时使用--delete
参数:使用--backup
时,默认会保护以~
结尾的文件不被删除,若自定义include/exclude规则,需自行加入相关规则;使用--backup-dir=DIR
时,若DIR
位于目标目录内,则每次同步时,原先的备份目录会被删除,从而会被移入新的备份目录,依次套娃。 - 增量备份:将每次更新内容(增量)放入新目录
--compare-dest=DIR
:提供对比目录,只有与对比目录不同的文件才复制到目标目录
--copy-dest=DIR
:类似--compare-dest
,未修改文件会本地复制到目标目录
--link-dest=DIR
:类似--compare-dest
,未修改文件会在目标目录建立本地硬链接
硬链接要求文件本身及元信息都一致,若后者不一致会本地复制文件并更新元信息。 - 在传输速度慢时,如通过网络传输的网速慢时,可使用参数
-z
启用压缩;但如果传输速度快时,如本地备份,则并不需要,压缩和解压需要额外占用CPU。 - include与exclude同时使用时,位于前面的参数优先级更高。比如想要同步忽略目录的子目录时,include应该置于exclude之前。此外,如果exclude的匹配规则太宽泛,比如
'*'
,此时若include未明确包含目录的子目录,则子目录会被排除在外,使用时需要小心。 - include/exclude匹配多个规则时
- 可将匹配规则列表置于
{}
中,但注意以,
分割且不能用空格!目录最好使用引号括起来,对于bash不是必须的,但在zsh中执行时会出错。此外,{}
内只有一个匹配规则时,规则后要加,
,否则不能按预期执行。 - 也可以使用include-from/exclude-from/filter,将文件列表或匹配规则放入单独的文件,每行一个文件或规则。当涉及多层子目录时有点复杂,需要逐层目录依次添加,具体可查看man文档,或参考下面的示例。
- 可将匹配规则列表置于
- 注意include/exclude路径首尾的
/
,匹配的目录会随之变化。- include/exclude路径开始的
/
代表同步源,而非系统根目录,文件匹配是以同步源目录为根目录的。如.*
代表所有隐藏文件(夹),会递归搜索整个同步源,而/.*
仅代表直接位于根目录下的隐藏文件(夹),而不会进行递归匹配,即不含根目录下非隐藏文件夹中的隐藏文件(夹)。因此备份$HOME
目录文件,但忽略隐藏的配置文件应--exclude="/.*"
,注意既不能省略/
,也不能用~/.*
。 - 如果不确定的话,谨慎起见建议include/exclude的匹配规则都以
/
起始,即通过相对路径来限制规则匹配的范围,以避免在意料之外引入或移除某些目录下的子文件或目录。 - include/exclude路径结尾加
/
时,代表匹配对象为路径,会忽略文件;不加/
则会同时匹配文件及路径。还是上面的例子,如要仅忽略$HOME
下的隐藏文件夹而不忽略隐藏文件,可以--exclude="/.*/"
- include/exclude路径开始的
- 注意同步源路径结尾的
/
,rsync的操作会随之而变。- 对于同步源路径:结尾不加
/
,代表同步的是整个源目录,包含源文件夹本身,会在目标路径下新建与同步源同名的文件夹;如果结尾加/
,则代表仅同步源目录下的内容,不含源文件夹,会将源目录下的内容直接复制到目标路径之下。 - 此外还会影响include/exclude的文件匹配:同步源路径结尾不加
/
,include/exclude匹配路径的根目录为源目录的上一级目录;结尾加/
,include/exclude匹配路径的根目录为源目录本身。 - 同步目标路径结尾是否加
/
似乎没有什么影响。
- 对于同步源路径:结尾不加
- 最后,保险起见,可以在实际运行之前通过参数
-n
(--dry-run
) 测试运行,与-v
配合可在不实际执行的情况下查看将会执行的操作。
下面是一个用于筛选配置文件的include规则文件示例:+
代表包含,-
代表排除,注意多层目录要逐层添加。
1 | + /.config |