同步 UNIX 文件( 三 )


还可以对源目录使用相同的用户/密码组合,从而从远程源目录复制到本地目录:$ rsync --recursive user@remote:dira dirb 。在通过 Internet 复制到远程系统时,还可以使用 --compress 选项在通过网络传输信息之前压缩信息,与原始字节复制相比,这可以大大提高效率 。当然,在复制到远程系统时,如果文件包含敏感信息,可能不希望复制原始文件 。在这种情况下,就需要使用加密 。
加密同步涉及的文件
使用文件同步解决方案的常见原因之一是,为了创建文件的精确备份,以便在出现问题时能够复制或重建目录结构的元素 。
rsync 工具非常适合完成这个任务,因为它只复制两个目录之间有差异的文件,效率很高 。更有意义的是,因为 rsync 可以同步到远程系统,所以可以使用它自动创建远程备份,不需要把备份文件单独复制到远程系统 。
这个过程的一个限制是,创建的拷贝是未加密的 。如果要把文件复制到远程系统,而其他人也能够访问这个远程系统,就需要确保其他人无法读取这些文件(即使他们能够接触到这些文件) 。
只使用 rsync 是无法加密文件的 。也无法使用 rsync 的算法只加密在上一次同步操作之后修改过的文件 。
但是,通过在脚本中执行 rsync,就可以用 rsync 的输出创建文件的辅助拷贝,然后对这个拷贝进行加密 。
这个脚本的基本原理是创建原目录结构的两个拷贝 。第一个拷贝作为参照拷贝,其中包含目录结构的精确副本 。这样,当再次同步目录时,就可以像一般情况一样比较源和目标文件并判断出差异 。在 rsync 命令中使用 --itemize-changes 选项,rsync 就会创建一个参照列表,其中列出在同步期间每个文件所发生的情况 。输出详细说明文件是否已经修改过(或新建),或文件是否已经删除 。清单 3 中给出一个示例 。
清单 3. rsync 生成的修改记录
 .d..t...... t1/a/
*deleting t1/a/3
.d..t...... t1/b/
>f.st...... t1/b/1
>ft1/b/6
以 .d. 开头的行表示新目录或目录修改 。*deleting 行表示文件已经从源目录中删除 。>f 行表示文件已经修改过或是新建的文件(>f) 。
通过解析这个输出文件,可以判断出源目录和目标参照目录之间的差异 。判断出差异之后,可以在第三个目录中创建原文件的加密版本 。通过使用修改记录,只加密(或删除)在上一次同步操作之后修改过的文件 。不能使用目录的加密版本直接执行同步,因为文件的加密版本总是与源文件不一样 。
完整的脚本见清单 4 。
清单 4. 完整脚本
 #!/usr/bin/perl
use warnings;
use strict;
use File::Basename;
use File::Path;
my $source = shift;
my $dest = shift;
my $encdest = shift;
if (!defined($source) || !defined($dest) || !defined($encdest))
{
print "Error: Not enough arguments!n";
print "Usage: $0 source destination encrypteddestn";
exit(1);
}
print STDERR "Running rsync between $source and $dest ($encdest)n";
system("rsync --delete --recursive --times -og --links --perms " .
"--hard-links --itemize-changes $source $dest " .
">/tmp/$$.rsynclog 2>&1");
open(DATA,"/tmp/$$.rsynclog") or dIE "Couldn't open the rsynclogn";
my @changedfiles;
my @delfiles;
while()
{
next if (m/sending incremental file list/);
chomp;
last if (length($_) == 0);
my ($changes,$filename) = split;
push @changedfiles,$filename if ($changes =~ m/^>f/);
push @delfiles,$filename if ($changes =~ m/^*del/);
}
close(DATA);
my $counter = 0;
foreach my $file (@changedfiles)
{
if (-f "$dest/$file")

推荐阅读