第十八章 归档和备份

前言

  1. 维护系统数据安全是计算机系统管理者的基本任务之一,及时创建系统文件的备份文件是维护系统数据安全的一种常用方法。
  2. 即便对于非系统管理员,经常创建备份文件或是在设备之间、文件夹之间移动大文件集通常都是非常有益的。
  3. 本章会介绍一些用于管理文件集合的常用命令:
  • 文件压缩程序:
    • gzip: 压缩和解压缩文件工具
    • bzip2: 块排序文件压缩工具
  • 文件归档程序:
    • tar: 磁带归档工具
    • zip: 打包和压缩文件
  • 文件同步程序:
    • rsync: 远程文件和目录的同步

文件压缩

基本介绍

  1. 在计算领域的发展历史中,人们一直在努力实现以最小的可利用空间存储最多的数据,其中可利用空间包括内存、存储设备或者网络带宽。
  2. 许多如今认为理所当然的数据服务,比如便携式音乐播放器、高清电视和宽带互联网等之所以能够存在,都应该归功于有效的数据压缩技术。
  3. 数据压缩是一个移除数据冗余信息的过程。现今的压缩技术则更为先进、更复杂,但基本目标一直是消除冗余数据信息。
  4. 压缩算法 (压缩采用的数学方法) 一般分为两大类:无损压缩与有损压缩。
  5. 无损压缩保留原文件中的所有数据,也就是说这种方式的压缩文件还原时,还原后的文件与原文件完全一致。
  6. 有损压缩,在压缩时为了实现更大程度的压缩而删除了某些数据信息,有损压缩文件还原时,与原文件并不是完全吻合,但是与原文件差别并不大。
  7. JPEG (图像压缩技术) 和 MP3 (音频压缩技术) 技术是典型的有损压缩实例。
  8. 下面的讨论中,仅仅涉及无损压缩,因为计算机上的大多数数据无法容忍任何数据损失。

gzip - 文件压缩与解压缩

  1. gzip 基本介绍
  • gzip 命令用于压缩一个或者更多文件。执行命令后,原文件会被其压缩文件取代。与之相反,gunzip 命令则将压缩文件还原为原文件。示例如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    [me@linuxbox ~]$ ls -l /etc > foo.txt
    [me@linuxbox ~]$ ls -l foo.*
    -rw-r--r-- 1 me me 15738 2012-10-14 07:15 foo.txt
    [me@linuxbox ~]$ gzip foo.txt
    [me@linuxbox ~]$ ls -l foo.*
    -rw-r--r-- 1 me me 3230 2012-10-14 07:15 foo.txt.gz
    [me@linuxbox ~]$ gunzip foo.txt
    [me@linuxbox ~]$ ls -l foo.*
    -rw-r--r-- 1 me me 15738 2012-10-14 07:15 foo.txt
  • 面对本例中,我们首先创建了一个名为 foo.txt 的文本文件,其内容为某目录所含文件的列表清单,然后运行 gzip 命令。于是,压缩后的文件 foo.txt.gz 便取代了原文件。
  • foo.* 表达式的文件,我们可以看到原文件已被其压缩文件取代,并且压缩后文件大小差不多才是原文件的 1/5 。此外,我们还可以看出,压缩后的文件与原文件有着相同的权限和时间戳。
  • 接着,我们运用 gunzip 命令进行解压缩,如此该压缩文件又被原始文件取代,而且权限和时间戳仍然会保持一致。
  1. gzip 选项
选项 功能描述
-c 将输出内容写到标准输出端口并且保持原有文件。也可以用 --stdout 或是 --to-stdout 替代
-d 解压缩。加上此选项, gzip 命令便类似于 gunzip。也可以用 --decompress 或 --uncompress 替代
-f 强制压缩,即便原文件的压缩版本已经存在了。也可以用 --force 替代
-h 显示有用信息,也可以用 --help 替代
-l 列出所有压缩文件的压缩统计。也可以用 --list 替代
-r 如果该命令行的操作参数中有一个或是多个是目录,那么递归压缩包含在目录中的文件。也可以 --recursive 代替
-t 检查压缩文件的完整性。也可以用 --test 代替
-v 在压缩时显示详细信息。也可以用 --verbose 代替
-number 设定压缩级别, number 是 1 (速度最快,压缩比最小) ~ 9 (速度最慢,压缩比最大) 范围中的一个整数。当然 1 ~ 9 的数值亦可以分别描述为 --fast 和 --best 。 gzip 默认的压缩级别是 6
  1. 案例
  • 回顾前面的例子
    1
    2
    3
    4
    [me@linuxbox ~]$ gzip foo.txt
    [me@linuxbox ~]$ gzip -tv foo.txt.gz
    foo.txt.gz: OK
    [me@linuxbox ~]$ gzip -d foo.txt.gz
  • 此例中,首先,我们将压缩文件 foo.txt.gz 取代了原文件 foo.txt 。接着,我们运用 -t、-v 选项检查压缩文件的完整性。最后,解压缩该文件为原来的形式。
  • 借助标准输入输出,gzip 有很多有趣的用法。
    1
    [me@linuxbox ~]$ ls -l /etc | gzip > foo.txt.gz
  • 此命令创建了一个目录列表的压缩版本。
  • gunzip 命令用于解压 gzip 的压缩文件,并且默默解压缩后缀为 .gz 的文件,所以,我们没有必要明确指定,只要指定名与已存在非压缩文件名不冲突就可以了。
    1
    [me@linuxbox ~]$ gunzip foo.txt
  • 如果只是希望查看某个压缩文本文件的内容,可以直接输入下面的命令行:
    1
    [me@linuxbox ~]$ gunzip -c foo.txt | less
  • 或者,利用 zcat 命令联合 gzip 一起,其效果等同于带有 -c 选项的 gunzip 。
  • zcat 的功能与 cat 命令相同,只是它的操作对象是压缩文件。用 zcat 命令处理 gzip 压缩文件的示例如下:
    1
    [me@linuxbox ~]$ zcat -c foo.txt | less
  • 同样也有 zless 命令,它与前面所讲的 less 的管道功能相同。

bzip2 - 牺牲速度以换取高质量的数据压缩

  1. bzip2 基本介绍
  • bzip2 程序由 Julian Seward 开发,与 gzip 命令功能相仿,但使用不同的压缩算法。该算法具有该质量的数据压缩能力,但却降低了压缩速度。多数情况下,其用法与 gzip 类似,只是用 bzip2 压缩后的文件以 .bz2 为后缀。
    1
    2
    3
    4
    5
    6
    7
    [me@linuxbox ~]$ ls -l /etc > foo.txt
    [me@linuxbox ~]$ ls -l foo.txt
    -rw-r--r-- 1 me me 15738 2012-10-17 13:51 foo.txt
    [me@linuxbox ~]$ bzip2 foo.txt
    [me@linuxbox ~]$ ls -l foo.txt.bz2
    -rw-r--r-- 1 me me 2792 2012-10-17 13:51 foo.txt.bz2
    [me@linuxbox ~]$ bunzip2 foo.txtb.z2
  • 由此例可以看出,bzip2 用法与 gzip 类似,前面所讨论的所有选项 (除了 -r 选项) ,bzip2 都支持。
  • 然而,要注意的是,两者的压缩级别选项 (-number) 有些许不同。与此同时,解压缩 bzip2 压缩文件的专用工具是 bunzip2 和 bzcat 命令。
  • bzip2 还配有专门的 bzip2recover 命令,该命令用于恢复损坏的 .bz2 文件。

文件归档

基本介绍

  1. 归档是与压缩操作配合使用的一个常用文件管理任务。
  2. 归档是一个聚集众多文件并将它们组合为一个大文件的过程,它通常作为系统备份的一部分,而且通常也用于将旧数据从某个系统移动某些长期存储设备的情况下。

tar - 磁带归档工具

  1. tar 基本介绍
  • tar 命令是类 UNIX 系统中用于归档文件的经典工具。
  • tar 是 tape archive 的缩写,由此可见,该命令最初始的作用就是磁带备份。虽然该命令仍可用于传统的磁带备份,但同样也可用于其他存储设备。
  • 大家肯定经常看到文件名以 .tar 和 .tgz 结尾的文件,它们分别是用普通的 tar 命令归档的文件和用 gzip 归档文件的文件。
  • tar 归档文件可以由许多独立的文件、一个或多个目录层次或者两者的混合组合而成,其用法如下:
    1
    tar mode[options] pathname...
  1. tar 操作模式
模式 描述
c 创建文件和/或目录列表的归档文件
x 从归档文件中提取文件
t 在归档文件末尾追加指定路径名
r 列出归档文件的内容
  1. tar 案例
  • tar 命令在选项的表达方式上有点奇怪,所以,我们需要据一些例子以说明其是如何工作的。首先,重新创建一个上一章中所建的 playground 文件夹。
    1
    2
    [me@linuxbox ~]$ mkdir -p playground/dir-{00{1..9},0{10..99},100}
    [me@linuxbox ~]$ touch playground/dir-{00{1..9},0{10..99},100}/file-{A..Z}
  • 下面,用 tar 命令为整个 playground 文件夹创建一个归档文件。
    1
    [me@linuxbox ~]$ tar cf playground.tar playground
  • 该命令行创建了一个叫做 playground.tar 的 tar 归档文件,该归档文件包含了 playground 文件夹的整个目录结构。
  • 从命令行中我们可以看出,tar 的命令操作模式 c 参数和用于指定归档文件名的 f 参数可以直接连着写在一起而中间不需要连字符隔开。
  • 然而,请注意,mode 参数必须在任何选项之前指定。
  • 下面的命令行用于列出归档文件的内容,可用于查看已经备份了哪些文件。
    1
    [me@linuxbox ~]$ tar playground.tar
  • 如若想要获取更详细的信息,可以增加 -v (详细信息) 选项。
    1
    [me@linuxbox ~]$ tar tvf playground.tar
  • 现在,将 playground 文件夹中的内容提取到一个新的位置。首先创建一个名为 foo 的新文件夹,然后切换工作目录,在提取该归档文件。
    1
    2
    3
    4
    5
    [me@linuxbox ~]$ mkdir foo
    [me@linuxbox ~]$ cd foo
    [me@linuxbox foo]$ tar xf ../playground.tar
    [me@linuxbox foo]$ ls
    playground
  • 查看 /foo/playground 目录下的内容,便会发现该归档文件已经成功提取,并且是源文件的精确复制。
  • 但是存在一个问题,除非是以超级用户的名义执行该命令,不然,从归档文件中提取出来的文件和目录的所有权属于执行归档操作的用户而不是文件的原始作者。
  • tar 命令处理档案文件路径名的方式也很有趣,其默认的路径名是相对路径而不是绝对路径,tar 命令创建归档文件时会简单地移除路径名前面的斜杠来实现相对路径。
  • 作为演示,下面会重新创建一个归档文件,此次明确指定一个绝对路径。
    1
    2
    [me@linuxbox foo]$ cd
    [me@linuxbox ~]$ tar cf playground2.tar ~/playground
  • 记住,当按下 Enter 键时,上面命令行输入的目录 ~/playground 会扩展为 /home/me/playground,也就是绝对路径。接下来,我们按照前面的步骤从归档文件中提取文件,注意观察所发生的变化。
    1
    2
    3
    4
    5
    6
    7
    8
    [me@linuxbox ~]$ cd foo
    [me@linuxbox foo]$ tar xf ../palyground2.tar
    [me@linux foo]$ ls
    home playground
    [me@linux foo]$ ls home
    me
    [me@linux foo]$ ls home/me
    playground
  • 此刻,我们便会发现当解压第二个归档文件是在当前工作目录 ~/foo 下重新创建了一个 home/me/playground 目录,而不是在认定的聚堆路径根目录下创建的。
  • 这样的工作方式看起来很奇怪,但是却更有用,因为如此可以将归档文件解压缩到任何目录下而不用被迫解压到源目录下,使用 -v 选项重复操作此实例可以详细地了解其运行情况。
  • 下面让我们看一个假想的但很实用的 tar 命令应用实例。假设我们需要将一个系统上的主目录及其内容复制到另外一个系统上,并且具备用于实现这一转移的 USB 大硬盘连接系统后,设备名为 BigDisk 。接着用 tar 进行文件归档,示例如下:
    1
    [me@linuxbox ~]$ sudo tar cf /media/BigDisk/home.tar /home
  • tar 归档的文件写入硬盘后,我们将硬盘卸载,再将其与另外一台计算机连接。同样,此硬盘挂载在了 /media/BigDisk 目录下。那么如何解压缩该归档文件,示例如下:
    1
    2
    [me@linuxbox2 ~]$ cd /
    [me@linuxbox2 /]$ sudo tar xf /media/BigDisk/home.tar
  • 当从归档文件中的所有文件采用的都是相对路径。
  • 当从归档文件中提取文件时,可以限制只提取某些文件。例如,如果希望从归档文件中提取单个文件,可以用如下命令行。
    1
    tar xf archive.tar pathname
  • 在命令后面添加要提取的文件的路径名,可以确保 tar 只恢复指定文件,而且可以指定多个路径名。注意,指定的路径名必须是存储在归档文件中的完整、准确的相对路径。在指定路径名时,通常不支持通配符。但是,GNU 版本的 tar 命令 (在 Linux 发行版本中该版本的 tar 最常见) 通过使用 –wildcards 选项而支持通配符。下面就是一个利用前面的 playground.tar 归档文件实践通配符的例子。
    1
    2
    [me@Linuxbox ~]$ cd foo
    [me@Linuxbox foo]$ tar xf ../playground2.tar --wildcards 'home/me/playground/dir-*/file-A'
  • 此命令行只会提取那些路径名与通配符 dir-* 匹配的文件。
  • tar命令创建归档文件时通常辅助以 find 命令。首先使用find命令查找到需要被归档的文件,然后借助 -exec 操作选项,启动 tar 的附加模式 r 将匹配文件添加到归档文件 playground.tar 中。
  • tar 命令结合 find 命令很适合创建目录数以及整个系统的增量备份,使用 find 命令找到那些在时间戳之后创建的文件,便可以创建一份只包含一次归档之后创建的文件的归档文件,当然假定该事件戳文件时在每个归档文件创建之后就立刻更新。
  • tar命令还可以利用标准输入输出。下面就是一个综合例子。
    1
    2
    [me@Linuxbox foo]$ cd 
    [me@Linuxbox foo]$ find playground -name 'file-A' | tar cf - --files-from=. | gzip
  • 本例中,先用 find 命令搜索得到匹配文件列表,然后将匹配文件再送至 tar 命令处理。如果文件名前面明确指定有连字符 - ,那就意味着这是标准输入输出的文件 (顺便讲一下,使用 - 代表标注输入/输出的惯例,其他许多程序也都采用) 。
  • --file-from 选项 (也可以简写成 -T) 则指定了 tar 命令从文件中而不是从命令行中读取文件路径名列表。
  • 最后,tar 命令归档后的文件在送至 gzip 进行压缩,由此得到压缩归档文件 playground.tgz 。
  • 后缀 .tgz 已经惯例性称为经 gzip 压缩的 tar 归档文件名的后缀,淡然,我们又是也用 .tar.gz 作后缀。
  • 虽然可以从外部使用 gzip 命令创建压缩归档文件,但现代 GNU 版本的 tar 命令则提供 gzip+z 选项和 bzip2+j 选项直接实现这一功能。
  • 以前面的例子为例,可以将命令行简化为一下命令行。
    1
    [me@Linuxbox ~]$ find playground -name 'file-A' | tar czf playground.tgz -T -
  • 当然,如果我们想要创建一个 bzip2 压缩的归档文件,可以这么做。
    1
    [me@Linuxbox ~]$ find playground -name 'file-A' | tar cjf playground.tbz -T -
  • 通过简单地将压缩选项从 z 变为 j (并将输出文件后缀改为 .tbz 以显示是 bzip2 压缩的文件) ,即可实现 bzip2 式的压缩归档文件。
  • 利用 tar 命令在系统之间传输网络文件,是 tar 另一个利用标准输入输出的有趣用法。
  • 假设,有两台类 UNIX 系统的计算机正在运行,并且都安装了 tar 命令和 ssh 命令,于是,我们便可以将远程系统 (本例中远程主机名叫做 remote-sys ) 中的某目录转移到本地系统。
    1
    2
    3
    4
    5
    [me@Linuxbox ~]$ mkdir remote-stuff
    [me@Linuxbox ~]$ cd remote-stuff
    [me@Linuxbox remote-stuff]$ ssh remote-sys 'tar cf -Documents' | tar xf -me@remote-sys's password:
    [me@Linuxbox remote-stuff]$ ls
    Documents
  • 上例中,名为 Documents 的目录从 remote-sys 的远程系统复制到本地系统上的 remote-stuff 的文件目录里。
  • 首先,用 ssh 程序在远程系统上启动 tar 命令,此时可能会联想到前面所讲的 ssh 具有在联网及其上运行的远程程序并将结果显示在本地系统的能力,也就是远程系统的标准输出送至本地系统显示。
  • 于是,利用这一特性,我们可以将 tar 命令创建的归档文件 (用 c 模式创建的) 送至标准输出而不是直接输出文件 (-f 选项) ,然后通过 ssh 建立的加密隧道将归档文件送至本地系统。
  • 在本地系统上,我们在执行 tar 命令提取 (x 模式) 标准输入的归档文件 (同样用 f 选项加上连字符作为参数) 。

zip - 打包压缩文件

  1. zip 基本介绍
  • zip 程序即使文件压缩工具也是文件归档工具。
  • Windows 用户肯定很熟悉这种文件格式,因为其读写的是 .zip 后缀的文件。然而,Linux 系统中,gzip 才是主要的压缩指令,而 bzip2 仅次之。
  • Linux 用户主要使用 zip 程序与 Windows 系统交换文件,而不是将其用于压缩或是归档文件。
  • zip 最基本的调用方式如下。
    1
    zip options zipfile file...
  1. zip 案例
  • 例如,创建一个 playground 的 zip 归档文件,可以输入下面的命令行。
    1
    [me@Linuxbox ~]$ zip -r playground.zip playground
  • 此例中,如果不加 -r 选项递归的话,只保留 playground 这个目录而不包括目录中内容。虽然程序会自动默认添加后缀 .zip,但为了以示清晰,最好还是在命令行中添加文件后缀。
  • zip 归档文件创建的过程中,zip 通常会显示如下的一系列信息。
    1
    2
    3
    4
    5
    adding:playground/dir-020/file-Z(stored 0%)
    adding:playground/dir-020/file-Y(stored 0%)
    adding:playground/dir-020/file-X(stored 0%)
    adding:playground/dir-087/ (stored 0%)
    adding:playground/dir-087/file-S (stored 0%)
  • 这些信息显示的是每个新添归档文件的状态。zip 使用两种存储方式向归档文件中添加文件。第一,不对文件进行压缩直接存储,如本例;第二,缩小文件大小,即对文件进行压缩后存储。紧随存储方法之后显示的数值表示的是实现的压缩比。
  • 由于使用的 playground 文件夹是空文件夹,所以并没有对齐内容进行压缩。
  • 利用 unzip,我们可以直接提取 zip 文件中的内容。
    1
    2
    [me@Linuxbox ~]$ cd foo
    [me@Linuxbox foo]$ unzip ../playground.zip
  • 关于 zip,有一点需要注意 (与 tar 命令相比) ,即如果指定的归档文件已经存在,那么 zip 仅仅只会更新而不会取而代之。这意味着原来存在的归档文件会保留下来,只是增加了一些新文件,原有匹配文件则被替换。
  • 通过给 unzip 指定提取的文件名,我们可以选择性地从 zip 归档文件中提取文件。
    1
    2
    3
    [me@linuxbox ~]$ unzip -l playground.zip playground/dir-087/file-Z
    [me@linuxbox ~]$ cd foo
    [me@linuxbox foo]$ unzip ../playground.zip playground/dir-087/file-Z
  • 使用 -l 选项,unzip 只会列出归档文件的内容而不会从中提取文件。
  • 如果没有指定任何文件,unzip 将会提取归档文件中的所有文件,我们可以增加 -v 选项得到更更详细的列表。注意当提取的文件与已存在文件冲突时,原文件被取代之前会提示用户是否执行此替换操作。
  • 与 tar 命令类似,zip 命令也可以利用标准输入输出,尽管此用法在某种程度上来说作用并不大。我们也可以用 -@ 选项将多个文件送至 zip 进行压缩。
    1
    2
    [me@Linuxbox foo]$ cd
    [me@Linuxbox ~]$ find playground -name "file-A" | zip -@ file-A.zip
  • 本例中,我们利用 find 命令产生一个匹配 -name 项的 file -A 文件列表,然后将结果直接作为 zip 命令的输入,从而得到一个包含选定文件的归档文件 file-A.zip 。
  • zip 同样可以将结果送至标准输出,但是由于只有极少的命令能够利用其输出结果,所以这种用法具有局限性。不幸的是,unzip 程序不支持标准输入,所以 zip 和 unzip 不能像 tar 命令一样一起用于处理网络文件。
  • 然而,zip 命令支持标准输入,所以可以用于压缩其他程序的输出结果。
    1
    2
    [me@linuxbox ~]$ ls -l /etc/ | zip ls-etc.zip -
    adding: - (deflated 80%)
  • 本例中,我们将 ls 的输出结果列表直接送给 zip 。与 tar 命令一样,zip 会默认默认的连字符代表输入的文件是标准输入。
  • 到目前为止,本章只涉及 zip 和 unzip 命令的一些基本用法,他们其实还有很多选项,尽管有些只适用于其他系统的特定平台,但是他们使用起来很灵活。zip 和 unzip 的 man 手册页都很全面,且包含了很多有用的例子。

同步文件和目录

基本介绍

  1. 将一个或多个目录与本地系统 (通常是某种可移动存储设备) 或是远程系统上其他的目录保持同步,是维护系统备份文件的常用方法。
  2. 例如,本地系统上有一个正在开发的网站备份,用户通常会在远程 Web 服务器上进行实时备份以实现同步更新。

在网络上使用 rsync 命令

  1. 通过网络复制文件是 rsync 用法的另一美妙之处。毕竟,rsync 命令名中的 r 其实指的是 remote (远程) 。
  2. 远程复制可以由以下两种方法中的任一种实现。
  3. 方法之一是针对于已安装了 rsync 命令以及诸如 ssh 等远程 shell 程序的系统。
  4. 假定本地网络有另外一个具有足够可利用硬盘空间的系统,同时希望利用远程系统而非外部设备进行备份操作。
  5. 假设远程系统已经有一个用于存放备份文件的 /backup 目录,那么我们便可以直接运行下面的命令。
    1
    [me@linuxbox ~]$ sudo rsync -av --delete --rsh=ssh /etc/home /usr/local remote-sys:/backup
  6. 此处命令行改动了两个地方。第一,增加了 --rsh=ssh 选项,该选项告诉 rsync 使用 ssh 命令作为其远程 shell 命令。只有这样,我们才可以通过SSH的加密隧道安全地从本地系统向远程主机传输数据。
  7. 第二,在 destination 路径名前指定了远程主机名 (本例中的远程主机名是 remote-sys) 。
  8. 方法之二,使用 rsync 服务器同步网络文件,通过配置 rsync 运行一个守护进行监听进来的同步请求。这种方法通常用于远程系统的镜像备份。
  9. 例如,Red Hat 软件为发行其 Fedora 系统,需要维持一个正在开发的大的软件包库。对于软件测试员来说,在发行版的测试阶段创建这个大集合的备份时很重要的,因为库中的文件会频繁变动,所以通过周期性的同步来维持本地文件镜像要批量复制软件库更可取。
  10. Georgia Tech 就维护了其中一个库,可以使用本地复制工具 rsync 以及 Georgia Tech 的 rsync 服务器来创建该库的镜像备份。
    1
    2
    [me@linuxbox ~]$ mkdir fedora-devel
    [me@linuxbox ~]$ rsync -av -delete rsync://rsync.gtlib.edu/fedora-linux-core/development/i386/os fedora-devel
  11. 本例中,使用 rsync 远程服务的 URI 是由协议 (rsync://) 、远程主机名 (rsync.gitlib.gatech.edu) 和库的路径名组成。

参考文章

  • 转载:Linux 命令行大全