使用 Unison 进行文件同步

作者:Mike Diehl

对于许多计算机用户来说,保持多台机器上的文件同步似乎是一个经常出现的问题。直到我发现了 Unison (http://www.cis.upenn.edu/~bcpierce/unison/) 之前,我从未真正找到一个完全令人满意的解决方案。

我们希望能够高效地保持两台或多台服务器完全同步,无论任何服务器上发生什么更改。在最简单的情况下,我们有一个生产服务器和一个备份服务器,我们需要保持它们同步。我们可能有一个服务器集群用于负载均衡配置。在最坏的情况下,我们可能有一组计算机,更改发生在任何或所有设备上。考虑一下我们在办公室有一台计算机、一台笔记本电脑和一台家里的工作计算机的情况。我们希望能够随时从任何计算机工作。

一种解决方案是简单地使用 scp (http://www.openssh.com/) 将文件从一台计算机复制到另一台或多台计算机。此解决方案要求我们指定一台计算机作为“主服务器”,并且只有在主服务器上发生的更改才会传播到其他从服务器。除了缺乏灵活性之外,此解决方案还有一个严重的缺点;它每次启动同步过程时都会将每个文件从主服务器复制到每个从服务器。在慢速网络连接或大型目录结构上,这通常被证明是不可行的。

一个稍微好一点的解决方案是使用 rsync。(http://samba.anu.edu.au/rsync/)rsync 程序仅传输那些不同的文件。实际上,rsync 仅传输给定文件中不同的部分。这种机制非常高效,但仍然存在 scp 所遭受的主/从架构问题。

有些解决方案依赖于内核服务,例如 FAM (http://oss.sgi.com/projects/fam/faq.html) 或集群文件系统,如 Coda。(http://coda.cs.cmu.edu/doc/html/index.html)当然,这些解决方案需要重新编译内核,这似乎只是为了保持几台服务器同步而做了很多工作。

到目前为止,unison 是我发现的最简单有效的解决方案。即使两台服务器上都发生更改,Unison 也能正确同步这两台服务器。如果同一文件在两台服务器上都发生更改,则会引起冲突,并且 unison 将显示错误消息。文件内容以及权限和所有权都可以同步。Unison 甚至允许您保持 Linux 机器和 Windows 机器同步。对于那些网络连接速度较慢的用户,很高兴知道 unison 的工作方式类似于 rsync,因为它只传输文件中已更改的部分(如果可能)。

安装 unison 非常简单。大多数 Linux 发行版中的软件包管理系统可以自动为您安装 unison。否则,只需下载源代码并编译它。不过,您需要安装 Ocaml。

Unison 可以配置为使用本机网络协议,或使用 OpenSSH 来传输文件。本机协议未经身份验证,也未加密,因此它不如 ssh 配置安全。我建议使用 ssh 配置,这也是我的示例将使用的配置。对于自动同步,您可能需要为 ssh 设置基于证书的身份验证。互联网上有许多易于遵循的说明来描述如何设置它,因此我不会在此处介绍。

一旦您安装了 unison 并配置了 ssh,就该开始同步了!但首先,我们应该简要讨论一下 unison 的工作原理,尤其是在第一次针对特定文件存储库运行时。第一次在文件存储库上使用 unison 时,该程序会记录两个存储库中每个文件的修改时间戳、权限、所有权和 i 节点号。然后,根据此信息,它决定哪些文件需要更新。该程序将所有这些信息存储在 ~/.unison 目录中。下次在文件存储库上运行 unison 时,更改很容易检测到。直观地,您可能会期望 unison 正在检查文件的内容以查看文件是否已更改,但事实并非如此。如果文件的修改时间戳和 i 节点号发生更改,则文件需要更新。这是一个非常快速的计算,并且可以很好地扩展,即使在非常大的文件上也是如此。

这是一个来自我的计算机的快速示例

unison /home/mdiehl/Development ssh://10.0.1.56///home/mdiehl/Development/ -owner -group -batch -terse

这应该都在一行上。我做了很多软件开发,在这个例子中,我使用 unison 将我的 Internet 可访问服务器上的开发目录同步到我私有网络上的工作站。即使这个例子相当直观,但它并没有变得更复杂,所以让我们仔细看看。

该示例将我的服务器上的 /home/mdiehl/Development 同步到我的工作站上的同一目录,该工作站的 IP 地址为 10.0.1.56。ssh 协议用于文件比较和传输。由于这是一个双向过程,因此脚本在哪里运行并不重要,只要两台机器可以通过网络相互访问即可;在服务器上运行我的脚本更方便,但如果我更改脚本中的 IP 地址,我也很容易从我的工作站运行此脚本。

“-owner”和“-group”参数告诉 unison 尝试同步用户和组所有权。您需要确保所有者和组存在于您打算同步的所有机器上。例如,如果您正在同步用户“bob”(其 uid 为 500)拥有的目录,则需要确保每个服务器上都存在“bob”。否则,您会发现 unison 将创建一个由 uid 500 拥有的整个目录结构。这很混乱,但很容易解决。

由于我从 cron 运行此示例命令,因此我使用“-batch”参数,该参数告诉 unison 不要向用户提出任何问题,如果存在任何冲突,只需尽力而为。同样,“-terse”参数使 unison 不会在我的 cron 日志中填充大量不必要的输出。

当我运行上面的示例时,我看到了两个计算机之间正在进行的更新列表。不过,最后几行是最重要的

UNISON 完成于 2008 年 4 月 13 日 01:05:15 的更改传播 同步完成(已传输 8 个项目,跳过 0 个,失败 0 个)

如您所见,需要传输 8 个文件才能同步两台服务器。幸运的是,没有问题,所有 8 个文件都已传输,并且我的两台机器恢复同步。如果文件有冲突的更改,那么我们会在“跳过”计数中看到它。如果出现文件权限或网络问题,那些问题将显示为失败。无论哪种方式,我们都想回顾日志以找出发生了什么。

在过去的几年里,我一直在使用 unison,我只遇到过一些问题。如前所述,最常见的问题源于存在冲突的文件更改。例如,如果您在一个服务器上更改一个文件,然后在另一个服务器上更改相应的文档,并且这些文件最终不是相同的,那么 unison 会将其视为冲突的更改并标记它。我通常解决此问题的方法是决定要保留哪个版本,并使用“-prefer”选项告诉 unison 在发生冲突时它应该...偏爱...哪个版本。在上面的示例中,如果我想让本地版本覆盖远程版本,我将添加

-prefer /home/mdiehl/Development

到命令行末尾。

我遇到的第一个 unison 问题是当我尝试同步两个目录时,这两个目录中有数万个文件。Unison 只是耗尽了内存。如果我对 unison 有一个抱怨,那就是我必须将大型文件存储库分成较小的部分才能使用 unison 同步它们。在我看来,簿记不应该占用那么多内存,但我无法反驳该工具有效并且我从未丢失过文件的事实。

unison 网站表明 unison 不再处于积极开发中。这很不幸,但这不应阻止您使用和信任该程序。我发现它非常成熟,并且仍然通过 unison 邮件列表获得积极支持。我有几次在邮件列表中寻求帮助,我发现该列表非常有帮助。

Unison 是一种非常有效的服务器同步方法。它可以在“星型”拓扑中使用,以保持多台服务器同步。它也可以在“环形”或您可能需要的任何其他拓扑中使用。文档非常详尽且编写良好。我希望您发现它像我一样有效且易于使用。

Mike Diehl 是新墨西哥州阿尔伯克基市桑迪亚国家实验室 Orion International 的 Linux 管理员。Mike 与他的妻子和两个小男孩住在一起。可以通过电子邮件联系 Mike:mdiehl@diehlnet.com

____________________________
相关内容
加载 Disqus 评论