2010年10月27日星期三

实现Linux双机文件同步rsync

rsync 有什么突出优点呢?首先,它被设计成只传送文件的不同部分,而非传送整个文件,以加速文件传输。比如,我正在写作本文,那我就可以现在使用 rsync 复制一次,而之后再进行一次传输。第二次(第三次、第四次……)父子文件的时候,rsync 只传送文件的不同部分。这将极大地节省时间,特别是在日常备份的过程中复制整个目录的时候。第一次复制会消耗较长时间,而下一次的传输就少多了(如果你每 天都不大幅修改目录的内容的话)。

rsync的另一个好处是它可以保留文件地所有权和访问权限信息以及复制符号链接,简而言之,它被设计成灵巧地掌控你的文件。

要安装 rsync,你应该不需要做什么 --- 一般的 Linux distro 都应该缺省安装它了。如果没有的话,你应该能在你的 distro 地软件包仓库里找到并安装它。如果你要把数据复制到远程系统上的话,两台机器都需要 rsync。

当你使用 rsync 把文件复制到另一台主机地时候,rsync 通常使用一个远程 shell,如 ssh 或 rsh 来工作。在下面的例子中,出于安全性的考虑,我们将只使用 ssh。当然,我们也可以访问使用 rsync daemon 的远程主机,不过,既然现在 ssh 几乎是无处不在的了,我们也没有必要费力气使用一个 daemon 了。

了解 rsync

rsync 的基本语法非常简单 --- 只要运行 rsync [options] source destination 就可以把文件从 source 复制到 destination。

所以,举个例子,如果你要把你归属目录里的文件复制到USB硬盘上去,你可以这么做:rsync -a /home/user/dir/ /media/disk/dir/ 。这里需要强调一下,对于 rsync 来说 "/home/user/dir/" 和 "/home/usr/dir" 是截然不同地。如果没有最后的斜线,rsync 会整个地复制目录;而有了最后的斜线,rsync 将只复制目录中的内容,而不创建目录本身。如果你想复制一个目录结构,那你就应该去掉结尾的斜线,比如在镜像 /var/www 到其他机器的时候或类似的情况。

在这个例子中,我加入了归档开关 (-a),这实际相当于同时使用几个 rsync 开关。它包括递归与复制符号链接开关、保留组与属主属性开关,总之就是让 rsync 适用于进行归档拷贝。注意,-a 不保留硬链接;如果你需要的话,还应该加上硬链接开关 (-H)。

另一个常用开关是 verbose (-v),这将让 rsync 报告更多信息。你还可以使用两个或三个 -v 开关 --- -v 将给出一些信息,-vv 会给出更多信息,而 -vvv 会把所有信息都给出来。

如果没有特别的选项,rsync 会连隐藏文件 (以 . 开头的文件) 一起复制的。如果你希望不复制隐藏文件,你应该加入开关 --exclude=".*/" 。你还可以使用 --exclude 来防止复制 vim 交换文件 (.swp) 或其他一些程序的自动备份文件 (.bak) 。

进行本地拷贝

假设你有一个外接 USB 或 1394 硬盘,你希望把 home 目录复制到外接驱动器上。一个不错的方法是把重要数据保存在一个顶级目录中,之后复制到外接硬盘地备份目录之中,命令如下:

rsync -avh /home/usr/dir/ /media/disk/backup/

如果你想保证本地删除的文件也在外接硬盘上被删除,你需要使用 --deleted 开关,如下:

rsync -avh --delete /home/user/dir/ /media/disk/backup

小心使用这个开关; 这个开关可能会让你在无意识的情况下删除一批无辜文件。事实上,当你要用 rsync 之前,使用 --dry-run 开关看一下要执行哪些操作而不真正同步文件可能是个好主意。如果你已经开始了一次 rsync 传输,却突然意识到这条命令可能造成数据损失的话,应该立刻用 Ctrl-C 来中止执行。一些文件可能已经损失掉了,不过你还有机会保存住剩下的。

进行远程拷贝

想要把文件复制到远程主机上? 没问题 --- 你需要做的就是加入主机和用户信息。举个例子,如果你想把同一个目录复制到远程主机上,你应该用:

rsync -avhe ssh --delete /home/user/dir/ [email protected]:dir/

如果你想知道文件传输的速度,以及还有多少需要复制,可以加上 --progress 开关:

rsync --progress -avhe ssh --delete /home/user/dir/ [email protected]:dir/

如果你不想每次使用 rsync 都被提示一次输入密码,确认一下你使用了 SSH 公钥机制而不是密码。要想这么做,你应该使用 ssh-keygen -t dsa ,并在密码提示环节直接按回车,以在本机上生成公钥。之后,使用 ssh-copy-id -i .ssh/id_dsa.pub [email protected] 把公钥复制到远端主机上。

如果你想从远端主机上找回一些以前的备份文件,可以使用如下命令:

rsync -avze ssh remote.host.com:/home/user/dir/ /local/path/

其中,z 开关会在传输过程中压缩数据,如果你在复制的文件在本地已经存在了,rsync 将不再传输 --- 这和把文件从本地传送到远端主机没什么区别。

用一个脚本进行封装

一旦你指出了哪些目录需要进行同步,确定了同步文件的命令,就可以很容易地把这些命令封装在一个简单脚本里。这是一个简单的例子:

rsync --progress -avze ssh --delete /home/user/bin/ [email protected]:bin/

rsync --progress -avze ssh --delete /home/user/local/data/ [email protected]:local/data/

rsync --progress -avze ssh --delete /home/user/.tomboy/ [email protected]:/.tomboy/

如果你是在交互模式下运行 rsync,可以使用 --progress 开关。如果不是交互模式的话,也就不需要这个开关了。

如果你看 rsync 的 man page 有可能会被它弄糊涂了。不过,当有了一些 rsync 的经验之后,你会发现设置 rsync 任务并不困难,它将为某天可能会来临的硬盘故障和数据损失做准备。

没有评论:

发表评论