如何在Ubuntu16.04上使用Unison备份大型目录
作为 Write for DOnations 计划的一部分,作者选择了 Free and Open Source Fund 来接受捐赠。
介绍
Unison是一个开源的文件同步工具。 在备份仅添加或更新少数文件的大型数据集方面非常有效。 例如,这种情况发生在公司 Samba 文件服务器或电子邮件服务器中。
这些服务器中的大部分文件将保持不变,而每天都会添加或修改少量文件。 Unison 能够极快地发现和备份这些新文件——即使存在数百万个文件和数 TB 数据。 在这些情况下,rsync 等传统工具可能需要更长的时间来执行相同的备份操作。
在本教程中,您将在一对服务器上安装和配置 Unison,并使用它来备份目录。 您还将配置 Unison 以使用 SSH 作为安全通信协议并创建 cron 作业 以定期运行 Unison。
先决条件
在开始本指南之前,您需要以下内容:
- 两台 Ubuntu 16.04 服务器,使用 Initial Server Setup with Ubuntu 16.04 指南进行配置。
- 通过阅读 如何使用 Cron 在 VPS 上自动执行任务,熟悉创建 crontab 条目。
本指南将使用两台服务器:
- primary 服务器:托管您将备份的数据的服务器。
- backup 服务器:将托管备份数据的服务器。
第 1 步 — 创建其他非根用户
Initial Server Setup with Ubuntu 16.04 教程指导您在 primary 和 backup 上创建名为 sammy 的非 root sudo 用户服务器。 在这一步中,您将创建两个新用户,一个在 primary 服务器上,一个在 backup 服务器上。 这可以防止您在阅读指南时产生混淆,如果在指南末尾启用了 SSH 安全配置,则需要在 备份 服务器上使用替代的非 root sudo 用户。
您需要在两个终端窗口中通过 SSH 以 sammy 用户身份登录 primary 和 backup 服务器。 以下两个 SSH 命令将使您登录到这些服务器:
ssh sammy@primary_server_ip ssh sammy@backup_server_ip
首先,在 primary 服务器上使用以下命令创建一个名为 primary_user 的新用户:
sudo adduser primary_user
然后给他们 sudo
访问权限:
sudo usermod -aG sudo primary_user
最后,更改为 primary_user 帐户:
su - primary_user
接下来,在 backup 服务器上执行相同的步骤,但创建一个名为 backup_user 的新用户。 确保您以这些用户的身份登录到 primary 和 backup 服务器,以完成本指南的其余部分。
现在您已经在两台服务器上创建了必要的用户,您可以继续安装 Unison 软件。
第 2 步 — 在两台服务器上安装 Unison
在此步骤中,您将在两台服务器上安装 Unison 软件包。
您将使用 Ubuntu 包管理器 apt
在两台服务器上安装 Unison。 在一段时间内第一次使用 apt
时,您应该使用以下命令更新本地包索引:
sudo apt-get update
这可确保您安装最新版本的 Unison。 这也将有助于避免安装错误。
接下来,安装 Unison:
sudo apt-get install unison
您现在已经完成了 Unison 的安装。 在下一步中,您将配置 SSH,以便 Unison 能够在两台服务器之间进行通信。
第 3 步 — 创建 SSH 密钥并配置 SSH
您需要做的第一件事是在 primary 服务器上创建一个 SSH 密钥对,因为您将使用基于密钥的身份验证进行 SSH 连接。 基于密钥的身份验证的优点是无需输入密码即可进行安全连接。 这很重要,因为您将创建一个自动备份过程,该过程必须在每次发生时都不需要您输入密码。
在 主 服务器上获得该密钥对后,您将把公钥复制到 备份 服务器,然后测试 Unison 是否能够使用 SSH 在服务器之间进行通信。
创建 SSH 密钥对时,通常使用强密码。 但是,Unison 会自动运行,所以每次运行时都不能手动输入密码。 在不输入密码的情况下按 ENTER
键。 这将生成一个无密码的 SSH 密钥对。
从 primary 服务器上的 primary_user 主目录运行以下命令,生成 SSH 密钥对:
ssh-keygen -t rsa -b 4096 -f .ssh/unison-primary
此处使用的选项含义如下:
-t rsa
:设置将要创建的密钥的类型。 RSA 密钥是最兼容的类型。-b 4096
:设置密钥的长度。 密钥越长,它就越安全。4096
的密钥长度是当前推荐的 RSA 密钥长度。-f .ssh/unison-primary
:设置键名和保存位置。 在这种情况下,您将使用您选择的名称将密钥保存到 SSH 的默认目录.ssh
中。
上面显示的命令在以下两个文件中创建公共和私有 SSH 密钥:
.ssh/unison-primary
.ssh/unison-primary.pub
第一个是 SSH 私钥,第二个是公钥。 您需要将公钥文件的内容复制到备份服务器。 显示用于复制的公钥文件内容的最简单方法是使用 cat
命令将内容打印到终端:
cat .ssh/unison-primary.pub
在 backup_user 主目录中的 backup 服务器上,使用文本编辑器打开 .ssh/authorized_keys
文件。 在这里,您将使用 nano
:
nano .ssh/authorized_keys
将公钥粘贴到编辑器中,然后保存并退出。
您现在可以通过 SSH 从 primary 服务器登录到 backup 来测试 SSH 配置是否正常工作。 这很重要,因为您需要接受并保存 备份 服务器的 SSH 服务器的密钥指纹,否则 Unison 将无法工作。 在 primary 服务器上的终端中,从 primary_user 的主目录运行以下命令:
ssh -i .ssh/unison-primary backup_user@backup_server_ip
-i .ssh/unison-primary
选项指示 SSH 使用特定的密钥或身份文件。 在这里,您将使用您创建的新 unison-primary
键。
按Y
然后按ENTER
接受指纹,然后登录退出。 您只需要确认 SSH 在服务器之间工作并保存 备份 服务器的 SSH 指纹。 指纹只能手动保存,因此必须在教程后面的过程自动化之前完成。
接下来,通过从 primary 服务器上的 primary_user 主目录运行以下命令来检查 Unison 是否会连接:
ssh -i .ssh/unison-primary backup_user@backup.example.com unison -version
在此命令中,您使用了与测试连接相同的 SSH 命令,并在末尾添加了 Unison 命令。 当命令放在 SSH 连接的末尾时,SSH 将登录,运行命令,然后退出。 unison -version
命令指示 Unison 打印其版本号。
如果一切正常,您将在 备份 服务器上看到显示 Unison 版本的响应:
Outputunison version 2.48.3
现在您已经确认 Unison 可以使用 SSH 密钥在服务器之间进行通信,您可以继续配置 Unison。
第 4 步 — 配置 Unison
在此步骤中,您将配置 Unison 以在从 primary 服务器到 backup 服务器的目录上运行简单的单向备份。
要配置 Unison,首先需要在 primary 服务器上的 primary_user 的主目录下创建配置目录:
mkdir .unison
接下来,您需要在 .unison
目录中的文本编辑器中打开一个名为 default.prf
的新文件。 此文件包含 Unison 配置。 使用以下命令打开文件:
nano .unison/default.prf
然后输入以下内容:
默认.prf
force = /home/primary_user/data sshargs = -i /home/primary_user/.ssh/unison-primary
这两行的含义如下:
force
:这确保更改是 only 从 主 服务器推送到 备份 服务器。/home/primary_user/data
路径是保存要备份的数据的目录的位置。sshargs
:此选项指示 Unison 使用您生成的 SSH 密钥。
如果您要备份的数据所在的目录不在 primary_user 主目录下,那么您必须确保它可以被 primary_user 读写。 如果您不熟悉 Linux 所有权和权限,请查看 Linux 权限简介 指南以了解更多信息。
Unison 现在已配置,因此您可以通过备份目录继续对其进行测试。
第 5 步 — 使用 Unison 备份目录
既然 Unison 已配置,您就可以备份目录了。 您将 primary 服务器上的 /home/primary_user/data
目录备份到 backup 服务器上的 /home/backup_user/data/
目录。 包含要备份的数据的目录 必须 与您在 force
选项旁边的 .unison/default.prf
中放置的目录相同。
您需要备份一些数据来测试 Unison 是否正常工作。 在 primary 服务器上创建一些空文件,然后检查 Unison 是否将它们传输到 backup 服务器。
首先,通过从 primary_user 主目录运行以下命令来创建将保存要备份的数据的目录:
mkdir data/
接下来,使用 touch
命令创建五个空文件:
touch data/file{1..5}
命令的最后一部分 file{1..5}
使用 Bash 大括号扩展来创建五个文件。 当 bash 给出 {1..5}
时,它会自动填充缺失的数字,2
、3
和 4
。 这种技术对于快速枚举多个文件很有用。
现在您已经有了 data
目录和一些要备份的测试文件,您可以运行 Unison 将文件备份到 backup 服务器。 以下命令将执行此操作:
unison -batch -auto /home/primary_user/data ssh://backup_user@backup_server_ip//home/backup_user/data
这些选项的含义如下:
batch
:不问任何问题就跑。auto
:自动接受任何不冲突的动作。
当您以简单的单向同步模式使用 Unison 时,您无需解决任何冲突。 这意味着您可以安全地设置这些选项。
只有在 Unison 的其他操作模式下才会发生冲突,其中它在两个方向上同步。 这样的用例将在某人的笔记本电脑和台式机上同步目录。 当他们更新桌面上的文件时,他们希望将更改推送到笔记本电脑,反之亦然。 如果在 Unison 同步发生之前在两端修改了相同的文件,则会发生冲突,并且 Unison 无法自动决定保留哪个文件以及覆盖哪个文件。
在单向推送模式下,始终保留 primary 上的数据,并覆盖备份上的数据。
此命令将在第一次运行时打印一条长消息。 消息内容如下:
OutputContacting server... Connected [//primary_server_ip//home/primary_user/data -> //primary_server_ip//home/backup_user/data] Looking for changes Warning: No archive files were found for these roots, whose canonical names are: /home/primary_user/data //backup_server_ip//home/backup_user/data This can happen either because this is the first time you have synchronized these roots, or because you have upgraded Unison to a new version with a different archive format. Update detection may take a while on this run if the replicas are large. Unison will assume that the 'last synchronized state' of both replicas was completely empty. This means that any files that are different will be reported as conflicts, and any files that exist only on one replica will be judged as new and propagated to the other replica. If the two replicas are identical, then no changes will be reported. If you see this message repeatedly, it may be because one of your machines is getting its address from DHCP, which is causing its host name to change between synchronizations. See the documentation for the UNISONLOCALHOSTNAME environment variable for advice on how to correct this. Donations to the Unison project are gratefully accepted: http://www.cis.upenn.edu/~bcpierce/unison Waiting for changes from server Reconciling changes dir ----> / Propagating updates UNISON 2.48.3 started propagating changes at 16:30:43.70 on 03 Apr 2019 [BGN] Copying from /home/primary_user/data to //backup_server_ip//home/backup_user/data [END] Copying UNISON 2.48.3 finished propagating changes at 16:30:43.71 on 03 Apr 2019 Saving synchronizer state Synchronization complete at 16:30:43 (1 item transferred, 0 skipped, 0 failed)
此信息警告这是第一次同步。 如果您在每次同步运行时都看到此消息,它还提供有关如何解决问题的提示。 最后一部分告诉您在此运行期间 Unison 同步了哪些数据。
在随后的每次运行中,它将打印更少的信息。 这是没有文件更新时的输出:
OutputContacting server... Connected [//primary_server_ip//home/primary_user/data -> //backup_server_ip//home/backup_user/data] Looking for changes Waiting for changes from server Reconciling changes Nothing to do: replicas have not changed since last sync.
这是在 primary 服务器上修改 /data/file1
时的输出:
OutputContacting server... Connected [//primary_server_ip//home/primary_user/data -> //backup_server_ip//home/backup_user/data] Looking for changes Waiting for changes from server Reconciling changes changed ----> file1 Propagating updates UNISON 2.48.3 started propagating changes at 16:38:37.11 on 03 Apr 2019 [BGN] Updating file file1 from /home/primary_user/data to //backup_server_ip//home/backup_user/data [END] Updating file file1 UNISON 2.48.3 finished propagating changes at 16:38:37.16 on 03 Apr 2019 Saving synchronizer state Synchronization complete at 16:38:37 (1 item transferred, 0 skipped, 0 failed)
每次同步运行后,backup 服务器将拥有 primary 服务器上 data
目录的精确副本。
警告: 运行 Unison 时,backup 服务器上 data
目录中的任何新文件或更改都将丢失。
您现在可以运行 Unison 来备份目录。 在下一步中,您将通过使用 cron 运行 Unison 来自动执行备份过程。
第 6 步 — 创建 Unison Cron 作业
在本节中,您将创建一个 cron 作业,该作业将运行 Unison 并以指定的频率将 data
目录备份到 backup 服务器。
crontab 是由 cron 进程读取的文件。 它包含的命令被加载到 cron 进程中,并以指定的时间间隔执行。
您可以通过运行以下命令来查看当前用户的 crontab 的内容:
crontab -l
-l
选项列出了当前用户的 crontab 的内容。 如果您之前没有编辑过 crontab,您将看到以下信息:
# Edit this file to introduce tasks to be run by cron. # # Each task to run has to be defined through a single line # indicating with different fields when the task will be run # and what command to run for the task # # To define the time you can provide concrete values for # minute (m), hour (h), day of month (dom), month (mon), # and day of week (dow) or use '*' in these fields (for 'any').# # Notice that tasks will be started based on the cron's system # daemon's notion of time and timezones. # # Output of the crontab jobs (including errors) is sent through # email to the user the crontab file belongs to (unless redirected). # # For example, you can run a backup of all your user accounts # at 5 a.m every week with: # 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/ # # For more information see the manual pages of crontab(5) and cron(8) # # m h dom mon dow command
接下来,在带有 -e
标志的 primary 服务器上运行 crontab
命令以在编辑模式下打开它:
crontab -e
如果您没有配置默认的命令行编辑器,您将在第一次运行命令时被要求选择一个编辑器。 选择您选择的编辑器以打开 crontab。
打开 crontab 后,将以下命令添加到现有文本下的第一个空行:
... * */3 * * * /usr/bin/unison -log -logfile /var/log/unison.log -auto -batch -silent /home/primary_user/data ssh://backup_user@backup_server_ip//home/backup_user/data
您将使用的命令与上面手动备份中使用的命令几乎相同,但有一些附加选项。 这些附加选项如下:
-silent
:禁用除错误以外的所有输出。 从 crontab 执行 Unison 时不需要正常输出,因为没有人可以读取它。-log
:指示 Unison 记录其操作。-logfile
:指定 Unison 将记录其操作的位置。
在此示例中,Unison 每 3 小时运行一次。 您可以将其更改为更符合您要求的任何频率。
每当您编辑 crontab 时,必须始终在底部放置一个空行,然后保存并退出,否则 cron 可能无法正确加载 crontab 文件。 这可能会导致命令无法执行。
完成这些更改后,保存并关闭文件。
接下来,在 primary 服务器上创建 Unison 将写入的日志文件。 以下命令将创建此文件:
sudo touch /var/log/unison.log
接下来,使 primary_user 成为文件的所有者。
sudo chown primary_user /var/log/unison.log
您可以通过读取 /var/log/unison.log
的日志文件来检查 Unison 备份的状态。 Unison 仅在备份新文件或更新文件或遇到错误时才会记录某些内容。
Unison 现在从 crontab 定期备份。 最后一个可选步骤是使 SSH 配置更加安全。
第 7 步(可选)- 保护 SSH
在本指南中,您创建并使用了一个没有密码的 SSH 密钥。 这是一个安全问题,您可以通过限制 backup_user 在通过 SSH 登录到 backup 服务器时能够执行的操作来解决。
您将通过将 SSH 配置为仅允许 backup_user 在通过 SSH 登录时执行单个命令来执行此操作。 这意味着您创建的 SSH 密钥只能用于执行 Unison 备份,不能用于其他任何操作。 这会导致您无法以 backup_user 的身份通过 SSH 连接到 backup 服务器。 这是因为登录需要的不仅仅是单个允许的命令。
如果您需要以 backup_user 身份访问 backup 服务器,请先以 sammy 用户登录,然后切换到 backup_user ] 使用 su - backup_user
。
在 /etc/ssh/sshd_config
的 backup 服务器上编辑 SSH 配置文件:
sudo nano /etc/ssh/sshd_config
然后将以下行添加到文件的底部:
/etc/ssh/sshd_config
Match User backup_user ForceCommand unison -server
这些配置选项将执行以下操作:
Match User
:当列出的用户登录时,SSH 将应用以下缩进的配置选项。ForceCommand
:这将匹配的用户限制为以下命令。 在这种情况下,backup_user 只能运行unison -server
命令。
保存并退出您的文本编辑器。 接下来,重新加载 SSH 服务以启用新配置:
sudo systemctl reload ssh.service
您可以通过尝试从 primary 服务器通过 SSH 以 backup_user 身份登录到 backup 服务器来测试这一点。
ssh -i .ssh/unison-primary backup_user@backup_server_ip
如果 /etc/ssh/sshd_config
设置正常,您将看到以下内容:
OutputUnison 2.48
SSH 会话将挂起,直到使用 CTRL
和 C
终止会话,因为 Unison 正在等待命令。
这表明在登录时自动调用了 Unison 服务器,除了与 Unison 服务器通信之外,无法进行其他访问。
您现在拥有一个工作且安全的 Unison 备份系统,可以根据需要随时备份您的数据。
结论
在本指南中,您安装并配置了 Unison 文件同步软件以通过 SSH 备份目录。 您还将 cron 配置为按照指定的计划自动运行备份并保护 SSH,这样无密码的密钥就不会被滥用。
在确定是否应该使用 Unison 时,您应该考虑以下几点:
- 当文件数量较少或数据量较少时,Unison 可能不是最佳选择。 在这种情况下,
rsync
将是更合适的选择。 您可以在 How To Use Rsync to Sync Local and Remote Directory on a VPS 指南中阅读有关使用 rsync 的更多信息。 - 备份大量数据可能需要很长时间,并且可能会耗尽您通过公共网络接口分配的带宽。 如果您的 primary 和 backup 服务器都是 DigitalOcean Droplets,那么如果您使用专用网络,您将能够更快、更安全地完成 Unison 备份。 有关免费 DigitalOcean 专用网络的更多信息,请参阅 专用网络概述 文档。