rsnapshot

出自 ArchWiki

Rsnapshot 是一个提供增量备份的开源实用程序。

安装

安装 rsnapshot 软件包。

配置

在安装过程中,配置文件会被创建。建议您备份此文件,以防您需要再次重新配置该文件。

# cp /etc/rsnapshot.conf /etc/rsnapshot.conf.default

/etc/rsnapshot.conf 文件有详细的注释,其中大部分内容应该是不言自明的。有关各种选项的完整参考,请查阅 rsnapshot(1)

根目录

选择您要存储文件系统备份的目录,在本例中,我将把备份存储在 /mnt/backups/

/etc/rsnapshot.conf
# All snapshots will be stored under this root directory.
#
snapshot_root   /mnt/backups/
注意: 字段之间用制表符分隔,而不是空格。这样做的原因是更容易指定路径中包含空格的文件路径。

外部程序依赖

取消注释引用 UNIX 命令 cpdussh(如果您要进行远程备份)和 rsnapshot-diff 等的行。文件中的这一部分应如下所示

/etc/rsnapshot.conf
# LINUX USERS:   Be sure to uncomment "cmd_cp". This gives you extra features.
# EVERYONE ELSE: Leave "cmd_cp" commented out for compatibility.
#
# See the README file or the man page for more details.
#
cmd_cp          /usr/bin/cp

# uncomment this to use the rm program instead of the built-in perl routine.
#
cmd_rm          /usr/bin/rm

# rsync must be enabled for anything to work. This is the only command that
# must be enabled.
#
cmd_rsync       /usr/bin/rsync

# Uncomment this to enable remote ssh backups over rsync.
#
cmd_ssh /usr/bin/ssh

# Comment this out to disable syslog support.
#
cmd_logger      /usr/bin/logger

# Uncomment this to specify the path to "du" for disk usage checks.
# If you have an older version of "du", you may also want to check the
# "du_args" parameter below.
#
cmd_du          /usr/bin/du

# Uncomment this to specify the path to rsnapshot-diff.
#
cmd_rsnapshot_diff      /usr/bin/rsnapshot-diff

# Specify the path to a script (and any optional arguments) to run right
# before rsnapshot syncs files
#
#cmd_preexec    /path/to/preexec/script

# Specify the path to a script (and any optional arguments) to run right
# after rsnapshot syncs files
#
#cmd_postexec   /path/to/postexec/script
注意: cmd_preexec 和 cmd_postexec 是在每次 rsnapshot 运行之前和之后运行的自定义脚本

保留先前的备份

Rsnapshot 允许命名的备份级别,这些级别会保留给定数量的先前备份。

在配置这些级别时,请注意列表中的第一个级别将是唯一一个实际从文件系统备份文件并轮换其自身先前备份的级别。其余级别将仅轮换先前的备份,并从列表中前一项创建的最旧备份中创建其最新备份。因此,这些级别在配置文件中列出的顺序非常重要。

替换 rsnapshot 配置文件中默认的 “BACKUP LEVELS / INTERVALS” 部分

/etc/rsnapshot.conf
retain  hourly  24
retain  daily   7
retain  weekly  4
retain  monthly 12
  • 当调用 rsnapshot hourly 时,将从文件系统创建一个新的备份,并保存在 <snapshot_root>/hourly.0/ 中。其余保留的备份将在每次命令运行时继续递增。因此,最终,原本是 <snapshot_root>/hourly.0 的内容将变为 <snapshot_root>/hourly.23/。然后,下次命令运行时,这将将被删除。
  • 当调用 rsnapshot daily 时,它将从 <snapshot_root>/hourly.23/ 备份(如果存在)创建 <snapshot_root>/daily.0/。否则,轮换的工作方式相同。
  • 同样,当调用 rsnapshot weekly 时,它将从 <snapshot_root>/daily.6/ 备份(如果存在)创建 <snapshot_root>/weekly.0/。对于配置的每个其他保留级别,模式都相同。

使用上述配置,您可以调用

rsnapshot hourly 每小时一次

rsnapshot daily 每天一次

rsnapshot weekly 每周一次

rsnapshot monthly 每月一次

这将为您提供可靠的 12 个月备份,同时最大限度地减少旧快照占用的空间。

如果您只想运行相同的配置,但只进行每日备份,则需要注释掉 hourly 备份级别。否则,调用 rsnapshot daily 将永远不会实际备份任何文件,因为它不是列表中的第一个。

备份

在本节中,您告诉 rsnapshot 您实际想要备份哪些文件。您首先放置一个 backup 参数,后跟您要备份的目录或网络路径的完整路径。第三列是您要备份到快照根目录内的相对路径。

/etc/rsnapshot.conf
###############################
### BACKUP POINTS / SCRIPTS ###
###############################

# LOCALHOST
backup  /home/          localhost/

在本示例中,backup 告诉我们这是一个备份点。/home/ 是我们要拍摄快照的目录的完整路径,而 localhost/ 是我们将要放入它们的 snapshot_root 内部的目录。使用单词 localhost 作为目标目录只是一种约定。您也可以选择使用服务器的完全限定域名而不是 localhost。如果您在一台专用备份服务器上拍摄多台机器的快照,则最好使用它们各自的主机名作为目录,以跟踪哪些文件来自哪个服务器。

远程系统

除了本地文件系统上的完整路径之外,您还可以使用 rsync over ssh 备份远程系统。如果您已安装并启用 ssh - 通过 cmd_ssh 参数 - 您可以指定如下路径

/etc/rsnapshot.conf
###############################
### BACKUP POINTS / SCRIPTS ###
###############################

# example.com
backup      root@example.com:/etc/     example.com/

这在根本上以相同的方式运行,但您必须考虑一些额外的事项

  • ssh 守护程序必须在 example.com 上运行
  • 您必须有权访问您在远程计算机上指定的帐户,在本例中是 example.com 上的 root 用户。
  • 您必须为 example.com 上的 root 用户启用基于密钥的登录,且不带密码短语。如果您想以另一个用户身份执行备份,您可以为源指定另一个用户(即 user@domain.com)。请注意,允许无密码短语的远程登录是一种安全风险,在您的情况下可能是可以接受的,也可能是不可接受的。请务必非常小心地保护对备份服务器的访问!有关如何设置此项的更多信息,请查阅 ssh 手册页,或有关使用 ssh 公钥和私钥的教程。您会发现基于密钥的登录在许多方面都更好,不仅对于 rsnapshot 而言,而且对于一般的便利性和安全性而言也是如此。您可以采取一项措施来减轻备份服务器泄露可能造成的损害:在客户端机器上创建 uid 和 gid 设置为 0 的备用用户,但使用更严格的 shell,例如 scponly。
  • 此备份通过网络进行,因此可能会较慢。由于这使用 rsync,因此在第一次备份期间最明显。根据您的数据更改量,后续备份应该会快得多,因为 rsync 仅发送文件之间的差异。

额外脚本

还有一个额外的 backup_script 行。使用此参数,第二列是要执行的备份脚本的完整路径,第三列是您要将其存储在本地路径(就像 backup 参数一样)。例如

/etc/rsnapshot.conf
backup_script      /usr/local/bin/backup_mysql.sh       localhost/mysql/

在本示例中,rsnapshot 将在临时目录中运行脚本 /usr/local/bin/backup_mysql.sh,然后将结果同步到快照根目录下的 localhost/mysql/ 目录中。

您的备份脚本只需将其执行的任何内容的内容转储到其当前工作目录中即可。它可以创建任意数量的文件和/或目录,但不应将其文件放在任何预先确定的路径中。这样做的原因是 rsnapshot 创建一个临时目录,更改到该目录,运行备份脚本,然后将临时目录的内容同步到您在第三列中指定的本地路径。典型的备份脚本是存档数据库内容的脚本。它可能看起来像这样

backup_mysql.sh
#!/bin/sh

/usr/bin/mysqldump -uroot mydatabase > mydatabase.sql
/bin/chmod 644 mydatabase.sql
注意
  • 确保您指定的目标路径是唯一的。备份脚本将完全覆盖目标路径中的任何内容,因此如果您尝试两次指定相同的目标,则只会留下最后一个脚本中的文件。幸运的是,rsnapshot 会在读取配置文件时尝试阻止您这样做。
  • 请记住,这些备份脚本将以运行 rsnapshot 的用户身份调用。在我们的示例中,这是 root 用户。确保您的备份脚本归 root 用户所有,并且其他任何人都不可写。如果您未能做到这一点,任何对这些备份脚本具有写入权限的人都将能够在其中放置将以 root 用户身份运行的命令。如果他们是恶意的,他们可能会接管您的服务器。

测试配置

当您完成所有更改后,您应该验证配置文件在语法上是否有效,以及所有支持程序是否在您认为它们所在的位置。为此,请使用 configtest 参数运行 rsnapshot

# rsnapshot configtest

如果一切正常,它应该显示 Syntax OK。如果存在问题,它应该准确地告诉您问题是什么。确保您的配置文件使用制表符而不是空格等。

测试配置的最后一步是以测试模式运行 rsnapshot。这将打印出它将要执行的操作的详细列表,而无需实际执行它们。要进行测试运行,请运行以下命令

# rsnapshot -t hourly

这告诉 rsnapshot 模拟 “hourly” 备份。它应该打印出它在实际运行时将执行的命令。

注意: 请注意,测试输出可能与实际执行略有不同,但这仅仅是因为测试实际上并没有执行程序稍后可能会检查的事情。例如,如果程序将创建一个目录,然后稍后测试以查看该目录是否存在,则测试运行可能会声称它将创建该目录两次,因为它实际上并没有在测试期间创建。这应该是您在运行测试时会看到的唯一类型的差异。

自动化

现在您已经设置好了配置文件,是时候设置 rsnapshot 以自动运行了。

首先创建一个服务文件

/etc/systemd/system/rsnapshot@.service
[Unit]
Description=rsnapshot (%I) backup

[Service]
Type=oneshot
Nice=19
IOSchedulingClass=idle
ExecStart=/usr/bin/rsnapshot %I

然后为您希望服务运行的每个间隔创建一个计时器单元(即 hourly、daily、weekly、montly)

/etc/systemd/system/rsnapshot-interval.timer
[Unit]
Description=rsnapshot hourly backup

[Timer]
OnCalendar=
Persistent=true
Unit=rsnapshot@interval.service

[Install]
WantedBy=timers.target

您可以使用以下命令验证您的 OnCalendar 条目是否有效并按您的预期工作(尤其是在您想要更改上述内容时)

# systemd-analyze calendar "Mon *-*-* 04:30:00"
注意: 通常最好安排较大的时间间隔在较小的时间间隔之前运行。这有助于防止每日任务在每小时作业完成之前尝试运行的竞争条件。应扩展相同的策略,以便每周条目在每日条目之前运行,依此类推。

然后,最后,启用/启动 它们,并验证生成的 单元状态 看起来良好,并且计时器按预期计划运行

# systemctl list-timers rsnapshot*

现在您可以等待第一个计时器触发,或者如果您想立即启动一个计时器,您可以 手动 执行。

外部驱动器

注意: 本节假定您已完成上面 #自动化 部分中描述的配置。

如果目标驱动器位于通过 USB 或 eSATA 连接的外部机箱中,则它可能在启动期间未挂载,或者在计划 rsnapshot 开始时可能已卸载。如果 rsnapshot 配置为写入始终存在的路径,例如 /.snapshots,则数据将备份到挂载为根目录的任何硬盘驱动器上,而不是所需的外部驱动器上。

为了解决这种情况,必须配置 rsnapshot 以依赖于磁盘被挂载到预期的挂载点。需要执行两个操作:更改 /etc/fstab/etc/systemd/system/rsnapshot@.service

Systemd 将读取 /etc/fstab 文件,并为其中的所有挂载点创建单元文件。对于此设置,我们需要向挂载点添加一个,可选地添加两个配置选项。在所需挂载点的选项列的末尾添加 x-systemd.automount,如果您希望挂载点在不活动后卸载,则添加 x-systemd.idle-timeout=10m。值 10m 可以更改为您希望的任何值。有关可用选项的更多详细信息,请参阅 systemd.automount(5)systemd.mount(5)

提示: 分区的 UUID 可以通过以 root 身份运行 blkid 找到。

一个挂载点示例

/etc/fstab
# /dev/sdd1
UUID=2848e78d-b05a-4477-a5f0-38f35411c269 /mnt/backups ext4 noauto,nofail,noexec,nouser,nosuid,rw,async,x-systemd.device-timeout=200ms,x-systemd.automount,x-systemd.idle-timeout=10m 0 2
提示: 有关可用选项的详细信息,请参阅 fstab(5)mount(8) § FILESYSTEM-INDEPENDENT MOUNT OPTIONS

更改 /etc/fstab 后,运行 daemon-reload,以便 systemd 获取所做的更改。检查挂载和自动挂载单元看起来是否正确

# systemctl show mnt-backups.mount
Where=/.snapshots
What=/dev/sdd1
Options=rw,nosuid,noexec,relatime,x-systemd.automount
Type=ext4
TimeoutUSec=1h
...
# systemctl show mnt-backups.automount
Where=/mnt/backups
DirectoryMode=0755
...

最后,编辑 /etc/systemd/system/rsnapshot@.service 并在 “[Unit]” 部分中添加以下行

/etc/systemd/system/rsnapshot@.service
[Unit]
Requires=mnt-backups.mount
After=mnt-backups.mount

为了确保一切配置正确,请检查 rsnapshot 服务单元现在是否需要挂载点

# systemctl show rsnapshot@daily.service | grep 'Requires='
Requires=sysinit.target system-rsnapshot.slice mnt-backups.mount
提示: 以 root 身份运行 journalctl -u mnt-backups.mount 以验证自动挂载和卸载是否按预期进行。

工作原理

我们有一个快照根目录,所有备份都存储在其中。在本示例中,这是目录 /mnt/backups/。在此目录中,为已定义的各种时间间隔创建其他目录。刚开始时它将是空的,但一旦 rsnapshot 运行了一周,它应该看起来像这样

[root@localhost]# ls -l /mnt/backups/
drwxr-xr-x    7 root     root         4096 Dec 28 00:00 daily.0
drwxr-xr-x    7 root     root         4096 Dec 27 00:00 daily.1
drwxr-xr-x    7 root     root         4096 Dec 26 00:00 daily.2
drwxr-xr-x    7 root     root         4096 Dec 25 00:00 daily.3
drwxr-xr-x    7 root     root         4096 Dec 24 00:00 daily.4
drwxr-xr-x    7 root     root         4096 Dec 23 00:00 daily.5
drwxr-xr-x    7 root     root         4096 Dec 22 00:00 daily.6
drwxr-xr-x    7 root     root         4096 Dec 29 00:00 hourly.0
drwxr-xr-x    7 root     root         4096 Dec 28 20:00 hourly.1
drwxr-xr-x    7 root     root         4096 Dec 28 16:00 hourly.2
drwxr-xr-x    7 root     root         4096 Dec 28 12:00 hourly.3
drwxr-xr-x    7 root     root         4096 Dec 28 08:00 hourly.4
drwxr-xr-x    7 root     root         4096 Dec 28 04:00 hourly.5

在这些目录中的每一个目录中,都是该时间点的完整备份。您在 backupbackup_script 参数下指定的目标目录路径直接粘贴在这些目录下。在示例中

backup          /etc/           localhost/

/etc/ 目录最初将被备份到 /mnt/backups/hourly.0/localhost/etc/

每次后续使用 hourly 命令运行 rsnapshot 时,它都会轮换 hourly.X 目录,然后将 hourly.0 目录的内容(使用硬链接)复制到 hourly.1 中。

当运行 rsnapshot daily 时,它将轮换所有 daily.X 目录,然后将 hourly.5 的内容复制到 daily.0 中。

hourly.0 将始终包含最新的快照,而 daily.6 将始终包含一周前的快照。除非快照之间的文件发生更改,否则 full 备份实际上只是指向同一文件的多个硬链接。因此,如果您的 /etc/passwd 文件在一周内没有更改,则 hourly.0/localhost/etc/passwddaily.6/localhost/etc/passwd 将完全是相同的文件。这就是 rsnapshot 如此节省空间的原因。如果文件在任何时候发生更改,则下一次备份将取消 hourly.0 中的硬链接,并将其替换为全新的文件。现在,这将占用之前两倍的磁盘空间,但仍然比拥有此文件 13 个完整唯一副本的空间要少得多。

请记住,如果您使用的间隔与本示例中的间隔不同,则列出的第一个间隔是从主文件系统直接获取更新的间隔。所有后续列出的间隔都从之前的间隔中提取。例如,如果您定义了 weekly、monthly 和 yearly 间隔(按该顺序),则 weekly 间隔将直接从文件系统更新,monthly 间隔将从 weekly 更新,yearly 间隔将从 monthly 更新。