对话 UNIX: rsync 的高级应用

保持多台机器同步很困难。幸运的是,有一个流行的工具可以简化这个任务:rsync

Martin Streicher, 软件开发人员, Pixel, Byte, and Comma

作者照片 - martin streicherMartin Streicher 是一位 Ruby on Rails 的自由开发人员和 Linux Magazine 的前任主编。Martin 毕业于 Purdue University 并获得计算机科学学位,从 1986 年起他一直从事 UNIX 类系统的编程工作。他喜欢收集艺术品和玩具。



2009 年 11 月 09 日

在过去 20 年间,计算机网络的使用量已经急剧增加了。Internet 的快速发展,国家和国际主干网络基础结构方面的大量投资,以及连网和计算硬件的价格下降,这些因素都促进了网络使用量的增加。目前,网络已经非常普及了,而且新的应用仍然在推动网络的规模和速度。Internet 最初出现在 几台小型工作站 上,但是现在连接着无数计算机。

常用缩写词

  • FTP:File Transfer Protocol
  • WebDAV: Web-based Distributed Authoring and Versioning

与此同时,UNIX® 也在发展,连网软件的功能日益强大。FTP 属于第一批用于在系统之间共享文件的工具,目前仍然在广泛使用。rcp(“remote copy” 的简写)改进了 FTP,它具有与传统 cp 实用程序相似的功能,但是它在机器之间复制文件。rdist 基于 rcp,它自动地把文件从一台机器分布到许多系统。

现在,这些工具都过时了:rcprdist 过时了是因为它们不安全。scp 替代了它们。FTP 仍然在广泛使用,但是应该尽可能使用 FTP 的安全版本 Secure FTP (SFTP)。还有其他工具,比如 WebDAV 和 BitTorrent™ 等。当然,机器越多,保持所有机器同步(或者至少保持一种已知状态)就越困难,scp 和 WebDAV 无法解决这个问题,除非您自己编写解决方案。

最好的文件分布工具是 rsyncrsync 可以在中断之后恢复传输;它只传输源文件和目标文件之间不一致的部分;rsync 可以执行完整备份或增量备份。更棒的是,在所有风格的 UNIX 上都可以使用 rsync,包括 Mac OS X,所以很容易连接任何系统。

我们先来回顾一下 rsync 的一般用法,然后讨论更高级的应用。这里采用的演示系统是 Mac OS X version 10.5 Leopard(FreeBSD 的一种变体)和 Ubuntu Linux® version 8。如果您使用其他操作系统,这里的大多数示例很可能可以移植。请阅读您机器上的 rsync 手册页,了解正确的操作。

快速回顾

cp 一样,rsync 也把文件从源复制到目标。但是,与 cp 不同,rsync 操作的源和目标既可以是本地的,也可以是远程的。例如,清单 1 中的命令把 /tmp/photos 目录及其内容按原样复制到主目录。

清单 1. 按原样复制内容
$rsync -n -av /tmp/photos ~
building file list ... done
photos/
photos/Photo 2.jpg
photos/Photo 3.jpg
photos/Photo 6.jpg
photos/Photo 9.jpg

sent 218 bytes  received 56 bytes  548.00 bytes/sec
total size is 375409  speedup is 1370.11

-v 选项启用详细消息。-aa 代表存档)是 -rlptgoD 的简写(递归地复制,把符号链接复制为符号链接,保留权限,保留组,保留所有者,保留设备和特殊文件)。通常,-a 会生成文件的镜像;但是,在目标系统不支持相同的属性时会出现例外。例如,把 UNIX 中的目录复制到 Windows® 时无法准确地映射。下面会对一些不太常见的情况给出建议。

rsync 有许多选项。如果担心指定的选项或者源或目标不正确,可以使用 -n 执行试运行。试运行 会预览对每个文件的操作,但是不会实际复制数据。当确认所有设置是正确的之后,删除 -n 选项,再次运行命令。

清单 2 中的示例说明了使用 -n 选项的重要性。清单 1 中的命令和下面的命令会产生不同的结果。

清单 2. 复制指定目录的内容
$ rsync -av /tmp/photos/ ~
./
Photo 2.jpg
Photo 3.jpg
Photo 6.jpg
Photo 9.jpg

sent 210 bytes  received 56 bytes  532.00 bytes/sec
total size is 375409  speedup is 1411.31

差异是什么?差异是源参数末尾的斜杠。如果源参数的末尾有斜杠,就会复制指定目录的内容,而不复制目录本身。目标参数末尾的斜杠没有作用。

清单 3 中的示例把同一个目录转移到另一个系统上。

清单 3. 把目录转移到另一个系统上
$ rsync -av /tmp/photos example.com:album
created directory album
Photo 2.jpg
Photo 3.jpg
Photo 6.jpg
Photo 9.jpg

sent 210 bytes  received 56 bytes  21.28 bytes/sec
total size is 375409  speedup is 1411.31

假设您在远程机器上有相同的登录名,rsync 会提示输入密码。提供正确的凭证之后,它创建目录 album 并把图像复制到这个目录中。在默认情况下,rsync 使用 Secure Shell (SSH) 作为传输机制;可以在 rsync 中重用机器别名和公共密钥。


rsync 模式

清单 2清单 3 中的示例演示了 rsync 的四种模式中的两个。第一个示例是 shell 模式,也称为本地模式。第二个示例是远程 shell 模式,它使用 SSH 执行底层连接和传输。rsync 还有两种模式。列表模式ls 相似:它列出源的内容,见 清单 4

清单 4. 列出源的内容
$ 
drwxr-xr-x         238 2009/08/22 18:49:50 photos
-rw-r--r--        6148 2008/07/03 01:36:18 photos/.DS_Store
-rw-r--r--       71202 2008/06/18 04:51:36 photos/Photo 2.jpg
-rw-r--r--       69632 2008/06/18 04:51:45 photos/Photo 3.jpg
-rw-r--r--       61046 2008/07/14 00:31:17 photos/Photo 6.jpg
-rw-r--r--      167381 2008/07/14 00:31:56 photos/Photo 9.jpg

第四种模式是服务器模式。在这种模式下,rsync 守护进程在一台机器上永久运行,接收文件传输请求。可以把文件发送给守护进程,也可以向它请求文件。服务器模式非常适合创建中心备份服务器或项目存储库。

远程 shell 模式和服务器模式的差异在于,后者在源和目标名中使用两个冒号 (:)。假设 whatever.example.com 存在,下面的命令把文件从源复制到一个本地目标:

$ rsync -av whatever.example.com::src /tmp

src 究竟是什么?它是在守护进程的主机上定义和配置的一个 rsync 模块。模块有名称、路径(包含它的文件)和其他一些参数,比如 read only 禁止修改内容。

执行以下命令运行 rsync 守护进程:

$ sudo rsync --daemon

不一定要作为超级用户(根用户)运行 rsync 守护进程,但是这种做法可以保护机器上的其他文件。在作为根用户运行时,rsync 通过使用 chroot 只访问模块的目录层次结构(路径)。执行 chroot 之后,其他所有文件和目录就看不到了。如果用自己的特权运行 rsync 守护进程,要选择未使用的套接字并确保它的模块有下载和/或上传所需的权限。清单 5 中的简单配置共享主目录中的一些文件,而不需要使用 sudo。这些配置存储在 rsyncd.conf 文件中。

清单 5. 用于共享文件的简单配置
motd file = /home/strike/rsyncd/rsync.motd_file
pid file = /home/strike/rsyncd/rsyncd.pid
port = 7777
use chroot = no

[demo]
path = /home/strike
comment = Martin home directory
list = no

[dropbox]
path = /home/strike/public/dropbox
comment = A place to leave things for Martin
read only = no

[pickup]
path = /home/strike/public/pickup
comment = Get your files here!

这个文件分为两部分。第一部分(前四行)配置 rsync 守护进程的操作。(还可以使用其他选项)。第一行指定一个文件,文件包含指明服务器的消息。第二行指定另一个文件,它记录服务器的进程 ID。在必须手工杀死 rsync 守护进程时,可以使用这个文件:

kill -INT `cat /home/strike/rsyncd/rsyncd.pid`

这两个文件放在主目录中,因为这个示例不使用超级用户特权运行软件。为这个守护进程选择大于 1000 的端口号,用户可以把这个范围的端口号分配给任何应用程序。第四行关闭 chroot

第二部分分为几个小节,每个模块一小节。每个小节包含标题行和模块的选项(键-值对)列表。在默认情况下,所有模块都是只读的;设置 read only = no 允许写操作。另外,在默认情况下,所有模块在模块编目中列出;设置 list = no 隐藏模块。

运行以下命令启动守护进程:

$ rsync --daemon --config=rsyncd.conf

现在,从另一台机器连接这个守护进程,省略模块名。应该会看到:

rsync --port=7777 mymachine.example.com::
Hello! Welcome to Martin's rsync server.

dropbox        	A place to leave things for Martin
pickup         	Get your files here!

如果没有在冒号 (::) 后面指定模块,守护进程会返回可用模块的列表。如果指定了模块,但是没有指定模块中的文件或目录,守护进程会提供模块内容的编目,见 清单 6

清单 6. 模块内容的编目输出
rsync --port=7777 mymachine.example.com::pickup
Hello! Welcome to Martin's rsync server.

drwxr-xr-x        4096 2009/08/23 08:56:19 .
-rw-r--r--           0 2009/08/23 08:56:19 article21.html
-rw-r--r--           0 2009/08/23 08:56:19 design.txt
-rw-r--r--           0 2009/08/23 08:56:19 figure1.png

通过指定模块和文件本地复制文件,见 清单 7

清单 7. 指定模块,本地复制文件
rsync --port=7777 mymachine.example.com::pickup/
Hello! Welcome to Martin's rsync server.

drwxr-xr-x        4096 2009/08/23 08:56:19 .
-rw-r--r--           0 2009/08/23 08:56:19 article21.html
-rw-r--r--           0 2009/08/23 08:56:19 design.txt
-rw-r--r--           0 2009/08/23 08:56:19 figure1.png

通过对掉源和目标目录,然后指定用于写操作的模块,可以执行上传,见 清单 8

清单 8. 对掉源和目标目录
$ rsync -v --port=7777 application.js mymachine.example.com::dropbox
Hello! Welcome to Martin's rsync server.

application.js

sent 245 bytes  received 38 bytes  113.20 bytes/sec
total size is 164  speedup is 0.58

快速回顾 rsync 之后,现在我们看看如何在日常任务中应用 rsyncrsync 对于备份尤其有用。另外,因为它可以同步本地文件及其远程副本(也可以对整个文件系统进行同步),它非常适合管理那些必须相同(至少是部分相同)的大型集群。


用 rsync 备份数据

定期执行备份是一项重要的任务,但是常常被忽视。每天运行长时间的备份可能很无聊,或者需要大量外部介质来存储文件;但是,不要找借口,为了保证数据安全,应该坚持每天备份数据。

为了简化这个任务,可以使用 rsync 并指定一个远程服务器,这个服务器可以是服务提供商提供并备份的服务器。您的每台 UNIX 机器可以使用相同的技术,这非常适合保护笔记本计算机上的数据。

在远程机器上生成 SSH 密钥和 rsync 守护进程,创建一个允许写的备份模块。完成之后,运行 rsync 创建每日备份,这个备份几乎不占用任何空间,见 清单 9

清单 9. 创建每日备份
#!/bin/sh
# This script based on work by Michael Jakl (jakl.michael AT gmail DOTCOM) and used 
# with express permission.
HOST=mymachine.example.com
SOURCE=$HOME
PATHTOBACKUP=home-backup

date=`date "+%Y-%m-%dT%H:%M:%S"`

rsync -az --link-dest=$PATHTOBACKUP/current $SOURCE $HOST:PATHTOBACKUP/back-$date

ssh $HOST "rm $PATHTOBACKUP/current && ln -s back-$date $PATHTOBACKUP/current"

HOST 替换为自己的备份主机名,把 SOURCE 替换为希望保存的目录。把 PATHTOBACKUP 改为自己的模块名。(还可以把脚本的最后三行嵌入一个循环,动态地修改 SOURCE,从而备份同一系统上的一系列目录)。备份的过程如下:

  • 首先,把 date 设置为当前日期和时间,产生 2009-08-23T12:32:18 这样的字符串,它惟一地标识备份。
  • rsync 命令执行复制操作。-az 保留所有文件信息并执行压缩。关键之处是 --link-dest=$PATHTOBACKUP/current,它指定如果文件没有修改过,就不把它复制到新的备份。相反,在新备份中创建一个指向现有备份中同一文件的硬链接。换句话说,新备份只包含已经修改过的 文件;其他文件都是链接。

    具体地说(展开所有变量),mymachine.example.com::home-backup/current 是当前存档。/home/strike 的新存档是 mymachine.example.com::home-backup/back-2009-08-23T12:32:18。如果 /home/strike 中的文件没有修改过,那么文件在新备份中表示为指向当前存档的硬链接。否则,把文件复制到新存档中。

    如果您每天只修改少量文件和目录,那么生成完整的备份实际上是没有意义的,这样做很浪费空间。另外,因为每个每日备份都非常小(除了第一个),可以保存长时间的文件历史。

  • 最后一步是更改远程机器上备份的组织,让新创建的存档成为当前存档,这会减小下一次运行脚本时要记录的差异。最后一个命令删除当前存档(这只是符号链接),重新创建相同的符号链接,但是指向新的存档。

请记住,硬链接指向相同的文件。硬链接的创建和维护开销很低,所以只使用增量方案就可以模拟完整备份的效果。


其他高级技巧

开始在日常任务中应用远程 rsync 之后,很可能会发现有必要让守护进程一直运行。Linux 和 UNIX 都为 rsync 提供了启动脚本,通常在 /etc/init.d/rsync 中。请在自己的操作系统中查找启动脚本以及启用和禁用组件的实用程序。如果您要按自己的方式作为守护进程运行 rsync,或者无法访问启动脚本,那么可以用 cron 启动 rsync

@reboot /usr/bin/rsync --daemon --port=7777 --config=/home/strike/rsyncd/rsyncd.conf

这个命令在机器每次启动时启动守护进程。把这一行放在 crontab 文件中并保存文件。

前面演示了如何用 -n 预览 rsync 将执行的操作,发现可能存在的问题。还可以使用两个选项监视传输的状态:--progress--stats。前者显示一个进度条。后者显示如何执行压缩和传输。可以使用 --compress 压缩两台机器之间传输的数据。在使用这个选项时并不发送原始数据,而是由发送方压缩数据,由接收方解压数据,这会加快传输速度 — 数据越少,花费的时间越少。

在默认情况下,rsync 会把源中的所有文件复制到目标。这就是复制。如果希望建立镜像(即目标是源的精确拷贝),那么应该指定 --delete。例如,如果源包含文件 A、B 和 C,标准的 rsync 会把 A、B 和 C 复制到目标。但是,如果在源中删除了 B,再次复制,目标就不再是源的镜像了:B 不再是有效的。--delete 选项建立镜像,从目标中删除源中不再存在的文件。

常常有一些文件不希望复制到备份或存档中。这些文件包括编辑器和其他实用程序创建的草稿文件(文件名常常以波浪线 [~] 结尾),以及许多不重要的文件,比如主目录中的 MP3 文件,如果需要的话,可以重新创建它们。可以使用模式排除某些文件。可以在命令行上指定模式,或者在文本文件中指定模式列表。还可以组合使用模式和 --delete-excluded 选项,从目标中删除这些文件。

要想通过命令行根据模式排除文件,应该使用 --exclude。请记住,如果模式中的任何字符对于 shell 有特殊含义,比如 *,那么应该把模式放在单引号中:

$ rsync -a --exclude='*~' /home/strike/data example.com::data

假设文件 /home/strike/excludes 包含下面的模式列表:

*~
*.old
*.mp3
tmp

就可以排除与这些模式匹配的所有文件:

$ rsync -a --exclude-from=/home/strike/excludes /home/strike/data example.com::data

结束语

既然了解了 rsync,您就无法为忽视备份找借口了。您还能有什么借口呢?只要适当地应用 rsync,您的数据就不会丢失了。现在有价值的文件都可以保存FIDOnet 中。

参考资料

学习

  • rsync:访问项目主页,进一步了解 rsync 及其开发进度。
  • rsync tutorial:阅读这份教程,了解 rsync 的相关信息。
  • rsync 手册页:阅读 rsync 的手册页。
  • 对话 UNIX:阅读本系列中的其他部分。
  • UNIX shells:了解关于 UNIX shell 的更多信息。
  • AIX and UNIX 专区:developerWorks 的“AIX and UNIX 专区”提供了大量与 AIX 系统管理的所有方面相关的信息,您可以利用它们来扩展自己的 UNIX 技能。
  • AIX and UNIX 新手入门:访问“AIX and UNIX 新手入门”页面可了解更多关于 AIX 和 UNIX 的内容。
  • AIX and UNIX 专题汇总:AIX and UNIX 专区已经为您推出了很多的技术专题,为您总结了很多热门的知识点。我们在后面还会继续推出很多相关的热门专题给您,为了方便您的访问,我们在这里为您把本专区的所有专题进行汇总,让您更方便的找到您需要的内容。
  • 技术书店 浏览关于这些主题和其他技术主题的图书。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=AIX and UNIX
ArticleID=445301
ArticleTitle=对话 UNIX: rsync 的高级应用
publish-date=11092009