首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

同步 UNIX 文件(1)

同步 UNIX 文件(1)

文件同步就是在一个位置添加、修改或删除文件时,在另一个位置添加、修改或删除同一个文件的过程。本文讨论三个实用程序,cp、tar 和 rsync,它们都有助于同步 UNIX 文件。cp 和 tar 命令的同步功能有限,而 rsync 提供很全面的选项;尽管如此,它们都有各自适用的场合。
用 cp 命令执行直接复制尽管 cp 命令并不是真正的同步命令,但它可能是在两个位置之间复制文件的最简单方法。对于单一文件复制,cp 显然是非常高效的:$ cp source destination。
要想复制整个目录结构,可以使用 -r 选项递归地把整个目录结构从一个位置复制到另一个位置:$ cp -r source destination。这种复制方法仅仅递归地复制文件和目录。文件的权限、所有者和其他元数据并不会复制到目标位置。可以使用 -p 选项保留复制的每个文件和目录的所有者、权限和时间:$ cp -pr source destination。
使用 cp 命令是最容易最公认的文件复制方法,但是 cp 的效率很低,而且如果不使用 NFS 这样的远程文件系统解决方案,就不可能把目录复制到远程系统上。
使用 tartar(tape archive 的简写)实用程序原来用于高效地把目录结构(包括文件和文件元数据)转换为二进制流,然后就可以把二进制流写到备份磁带上。
通常使用 tar 创建一个包含所需目录的 .tar 文件:$ tar cf mydir.tar ./mydir。c 选项让 tar 创建新的存档文件,f 选项使用后面的参数指定要创建的存档文件的名称 (mydir.tar)。其余参数指定应该包含在存档文件中的文件或目录。tar 命令自动地递归遍历目录结构,所以如果指定包含一个目录,tar 将在存档文件中包含这个目录以及其中的所有文件和目录。
tar 的一个重要特点是,用户指定的路径名被看作绝对路径。也就是说,如果为 tar 指定完整的目录位置,例如 /etc 目录:$ tar cf etc.tar /etc。那么,在默认情况下,tar 将把文件提取到它们的绝对位置。例如,如果提取这个存档文件:$ tar xf etc.tar,就会在 /etc 目录中重新创建文件和目录结构。这可能会产生破坏(可能会覆盖 /etc 中希望保留的文件)。这个问题有两种解决方法。第一种是使用 GNU tar,它支持通过 --strip-path 选项从提取的路径中删除元素。
另一个简单的解决方法是进入父目录,然后使用相对路径(见清单 1)。
清单 1. 进入父目录并使用相对路径
1
2
$ cd /
$ tar cf etc.tar ./etc




在提取存档文件时,会在相对位置重新创建文件。可以使用这种方法帮助同步目录。因为 tar 创建目录结构的字节流,可以通过结合使用 tar 和管道把文件从一个位置复制到另一个位置:$ tar cf - ./etc |( cd /backup; tar xf - )。“-” 指定 tar 应该使用标准输出(在写时)或标准输入(在读时)。圆括号让语句在一个子 shell 中执行。看一下管道符前面的代码,它创建文件的字节流并发送到标准输出。在管道符后面,切换到另一个目录,然后从标准输入提取字节流。
要想保留文件的所有者和权限,可以使用 p 选项保留每个文件和目录的元数据:$ tar cfp - ./etc |( cd /backup; tar xfp - )。
掌握这种基本结构之后,就可以执行更复杂的操作。例如,可以只复制在特定时间之后修改过的文件:$ tar cf - --newer 20090101 ./etc |(cd /backup; tar xf - )。这个命令创建在 2009 年 1 月 1 日之后修改过的文件的拷贝。
通过与 rsh 或 ssh 结合使用,还可以把文件同步到远程主机:$ tar cfp - ./etc |(ssh user@host -- tar xfp -)。按照这种方式使用 ssh 和 tar 是在远程主机上创建本地文件备份的好方法。但是,还有更高效的信息同步方法。
使用 rsync 进行智能化同步前面介绍的文件同步方法的主要问题是,它们会复制每个文件(和相关联的目录结构)。如果您打算创建信息的新拷贝,这就没关系;但是,如果要同步两个目录中的信息,这种方法的效率很低。
假设一个目录中有 10,000 个文件,它们占用 100GB 的空间。如果修改了一个 10MB 的文件,在使用 cp 或 tar 进行同步时,就必须重新复制所有 100GB 文件。对于备份,复制如此大量的信息是很过分的。我们希望尽可能快速有效地完成备份。显然,如果知道哪些文件修改过了,就可以只复制这些文件,但是不总是能够知道这一信息。
tar 的 --newer 选项的作用是有限的,因为必须知道上一次修改的准确时间。rsync 工具能够解决这个问题。它会比较目录结构和各个文件,判断源目录和目标目录之间的差异。在查明哪些文件和目录已经修改了之后,它只把这些文件和目录复制到目标位置。另外,rsync 对各个文件使用相似的算法,只复制文件中修改过的部分。
按照最简单的形式,可以使用 rsync 把一个目录同步到一个新目录,例如:$ rsync -r a b。这会创建新目录 b,其中包含目录 a 中目录结构的拷贝。-r 选项让 rsync 递归遍历目录并复制整个目录结构。但是,如果目标目录已经存在,就会在目标目录 b 中创建一个新目录 a,其中包含文件的拷贝。这会有一些糟糕的副作用。例如,如果要把多个目录复制到备份目录,就会像清单 2 这样做。
清单 2. 把多个目录复制到备份目录
1
2
3
$ mkdir backup
$ rsync dira backup
$ rsync dirb backup




清单 2 创建目录 backup/dira,其中包含原来 dira 目录的拷贝。它还创建目录 backup/dirb,其中包含原来 dirb 目录的拷贝。后面的情况就不一样了:$ rsync dira backup/dira。在第一次使用时,这个脚本的作用符合期望。但是,在第二次使用时,rsync 会在指定的目标目录中创建目标目录,也就是创建 backup/dira/dira 目录。这不仅没有创建我们需要的结构,还造成了内容重复(其中一个版本是没有同步的)。
在使用 rsync 时,可能需要指定另外几个选项。默认的同步并不复制文件元数据,而且像对待普通文件那样对待某些特殊文件(比如链接)。希望使用的主要选项包括:
  • --delete —— 从目标目录中删除源目录中不再存在的文件。默认模式仅仅同步文件修改并创建新文件。在默认情况下,如果在源目录中删除了一个文件,就会忽略它,并不在目标目录中相应地删除它。通过使用这个选项,可以创建完全相同的同步。
  • --recursive —— 递归地复制目录和文件。
  • --times —— 同步每个文件和目录的修改时间和创建时间。
  • --owner —— 如果可能的话,保留文件的所有者。
  • --group —— 如果可能的话,保留组所有者。
  • --links —— 把符号链接复制为符号链接,而不是复制文件数据并解释源链接。
  • --perms —— 保留文件权限。
  • --hard-links —— 保留硬链接(在目标目录中创建硬链接),而不是复制文件内容。
其中一部分选项只能在两个系统的配置完全相同的情况下使用。例如,只有在源和目标计算机对相同用户使用相同 ID 的情况下,才能保留文件所有者和组所有者设置。
除了本地复制之外,rsync 还可以使用 ssh 执行远程复制。为此,需要在源目录或目标目录前面指定用户名和远程主机。例如,为了把一个目录同步到远程系统 user 上,执行以下命令:$ rsync --recursive dira user@remote:/backup/dirb。如果没有设置无密码 ssh 连接,那么会提示您输入远程密码。如果已经设置了连接,就可以用这种方法执行无人值守的夜间备份。
还可以对源目录使用相同的用户/密码组合,从而从远程源目录复制到本地目录:$ rsync --recursive user@remote:dira dirb。在通过 Internet 复制到远程系统时,还可以使用 --compress 选项在通过网络传输信息之前压缩信息,与原始字节复制相比,这可以大大提高效率。当然,在复制到远程系统时,如果文件包含敏感信息,可能不希望复制原始文件。在这种情况下,就需要使用加密。
返回列表