第十八章 归档与备份
第十八章 归档与备份
保证系统数据安全,其中一种实现方法是及时备份系统文件。即使不是系统管理员,制作备份、转移大批量文件往往是有好处的。
用于管理文件集合的常用程序:
-
文件压缩程序。
- gzip:压缩或解压缩文件。
- bzip2:块排序文件压缩器。
-
归档程序。
- tar:磁带归档实用工具。
- zip:压缩工具。
-
文件同步程序。
- rsync:远程文件和目录同步。
压缩文件
数据压缩是指移除冗余数据的过程。考虑一个例子,假设有100像素x100像素的纯黑图像文件。就数据存储而言(假设每个像素点占用24bit,也就是3B),该图像则需要30 000B的存储空间:
100x100x3 = 30 000
只有一种颜色的图像包含的全部都是冗余数据。要是聪明的话,在编码图像数据的时候,只简单描述有10000个黑色像素点就够了。因此,用不着存储包含30000个0值字节(黑色在图像文件中通常用0表示)的数据块,可以将这些数据用数字10000,其后跟一个0来表示。这种数据压缩方案称为游程编码(run-length encoding), 属于基本的压缩技术。虽然如今的压缩技术腰线进、复杂得多,但基本目标仍是消除冗余数据。压缩算法(用于实现压缩的数学方法)一般分为两类:
-
无损压缩:无损压缩保留文件中的所有数据。这意味着恢复后的文件和之前按未压缩的文件一模一样。
-
有损压缩:在压缩时为了实现更高的压缩比例,会删除部分数据。更大程度的压缩删除了某些数据信息,有损压缩文件还原后,与源文件并不一致,但差别不大。JPEG(图像压缩技术)和MP3(音频压缩软件)就是典型的有损压缩。
下面的讨论只涉及无损压缩。
gzip
gzip程序可用于压缩单个或多个文件。该程序在执行时,会使用原文件的压缩版本替换原文件。对应的gunzip用于解压缩。其命令如下:
gzip source #压缩文件source.gz
gunzip source #解压缩文件source.gz
例如:压缩foo.txt:
[me@linuxbox ~]$ ls -l /etc > foo.txt
[me@linuxbox ~]$ ls -l foo.*
-rw-rw-r-- 1 me me 11309 May 14 14:08 foo.txt
[me@linuxbox ~]$ gzip foo.txt
[me@linuxbox ~]$ ls -l foo.*
-rw-rw-r-- 1 me me 11309 May 14 14:08 foo.txt.gz
[me@linuxbox ~]$ gunzip foo.txt
[me@linuxbox ~]$ ls -l foo.*
-rw-rw-r-- 1 me me 11309 May 14 14:08 foo.txt
在这个例子中,首先创建一个foo.txt文件,其内容为当前工作目录的文件列表。然后执行gzip,将原文件替换为压缩问foo.txt.gz。在通配符foo.*产生的文件大小列表中,可以看到原文件已被其压缩版本取代,压缩后的文件大小差不多时原文件大小的1/5。可以看出压缩文件和原文件的权限和时间戳时一样的。
接下来,执行gunzip解压缩文件。在这之后,可以看到压缩文件被原文件替代,文件权限和时间戳也一并保留了下来。
常用的gzip选项
选项 | 描述 |
---|---|
-c, --stdout, --to-stdout | 将输出结果写入标准输出,保留原文件 |
-d, --decompress, --uncompress | 解压缩。利用它可以把gzip当作gunzip使用 |
-f, --force | 强制压缩,哪怕原文件的压缩文件已经存在 |
-h, --help | 显示用法信息 |
-l, --list | 列出压缩文件的压缩统计信息 |
-r, --recursive | 如果命令行参数时目录,则递归压缩目录中的文件 |
-t, --test | 测试压缩文件的完整性 |
-v, --verbose | 在压缩时显示详细信息 |
-number | 设置压缩级别。number时范围为1(速度最快,压缩级别最低)~9(最慢,压缩级别最高)的整数。1和9也可以分别用–fast和–best表示。默认值是6 |
可以使用-t和-v选项测试该标准压缩文件的完整性。例如:
[me@linuxbox ~]$ gzip foo.txt
[me@linuxbox ~]$ gzip -tv foo.txt.gz
foo.txt.gz:OK
[me@linuxbox ~]$ gzip -d foo.txt.gz
借助标准输入和标准输出,gzip还有一些有趣的用法:
[me@linuxbox ~]$ ls -l /etc | gzip > foo.txt.gz
该命令目录列表制作成了压缩文件。
如果只想查看压缩的文本文件内容,可以这样做:
[me@linuxbox ~]$ gunzip -c foo.txt | less
gzip附带了一个叫作zcat的程序,其功能等同于带有-c选项的gunzip。可以像cat命令那样查看gzip压缩过的文件内容:
[me@linuxbox ~]$ zcat foo.txt.gz | less
窍门
还有一个zless程序,其功能等同于上面的管道操作符。
bzip2
朱利安·苏厄德(Julian Seward)编写的bzip2程序类似于gzip,但使用了不同的压缩算法,在牺牲压缩速度的情况下实现了更高的压缩率。其用法于和gzip基本上差不多。扩展名为.bz2代表经过bzip2压缩的文件:
[me@linuxbox ~]$ ls -l /etc > foo.txt
[me@linuxbox ~]$ ls -l foo.txtls
-rw-r–r-- 1 me me 11309 May 14 14:08 foo.txt
[me@linuxbox ~]$ bzip2 foo.txt
[me@linuxbox ~]$ ls -l foo.txt.bz2
-rw-rw-r-- 1 me me 2013 May 14 14:08 foo.txt.bz2
[me@linuxbox ~]$ bunzip2 foo.txt.bz2
gzip选项除了-r都适用于bzip2.但是要注意,压缩级别选项(-number)的含义对bzip2有些不一样。bzip2还带有用于解压缩的bunzip2和bzcat。
bzip2另配有用于恢复受损的.bz2文件的bzip2recover程序。
不要试图二次压缩那些已经使用过高效压缩算法压缩过的文件,因为所有的压缩技术都涉及一些额外信息,这些额外信息被添加到文件中来描述压缩过程。尝试压缩不包含任何冗余信息的文件,省下来的那点空间根本不足以抵消额外信息使用的空间。
文件归档
与压缩分不开的另一项常见的管理任务是归档。收集多个文件,将其组合成一个大文件,这个过程就是归档。归档通常作为系统备份的一部分,也用于将旧数据从系统转移到某些长期存储设备中。
tar
tar(磁盘归档,tape archive) 程序是类UNIX系统的软件世界中里一款经典的文件归档工具。虽然tar依然能够从事“老本行”,但也同样可用于其他种类的存储设备。扩展名为.tar和.tgz的文件,分别代表普通tar归档文件和经过gzip压缩的归档(简称归档)。tar归档的组成可以是多个独立的文件、一个或多个目录层次或者两者兼而有之。tar用法如下:
tar mode[options] pathname ...
其中mod是tar模式
tar模式
模式 | 描述 |
---|---|
c | 根据指定的一组文件或目录创建归档 |
x | 提取归档内容 |
r | 将指定的路径名追加到归档末尾 |
t | 列出归档内容 |
例如:创建playground目录的tar归档:
tar cf playgound.tar playground
该命令创建了一个名为playground.tar的归档,其中包含了整个playground目录的层次结构。从该命令可以看到,模式和用于指定归档名称的f选项可以合并书写,前面也不需要连字符。但是要注意,模式必须先于其他选项出现。
想要列出归档内容,可以这样:
tar tf playground.tar #列出playgound.tar的内容
要想获取更详细的清单,可以添加v(verbose)选项:
tar tvf playground.tar
将归档文件提取到新位置:
tar xf playround.tar #将playgound.tar提档到当前目录。
创建归档,指定绝对路径:
tar cf playgound2.tar ~/playground #将~/playground归档到playground2.tar
可以限制提取某些文件。例如,如果只想从归档中提取单个文件,可以这样:
tar xf archive.tar pathname
pathname就是要找提取的文件,可以指定多个路径名。路径名必须和归档中保存的相对路径名一模一样。指定路径名时,一般不支持通配符;但是GNU版本的tar(Linux发行版大多是这个版本)通过–wildcards选项加入对通配符的支持。来看一例子:
tar xf ../playground2.tar --wildcards 'home/me/playground/dir-*/file-A'
该命令只提取路径名中包含统配符dir-*的文件。
tar经常配合使用find来创建归档。我们使用find生成了一组进行归档文件:
find playground -name 'file-A' | xargs tar rf playground.tar
在这里,使用find命令查找playground目录中所有名为file-A的文件,然后使用xargs命令,以追加方式®调用tar,将查找到的文件添加到归档文件playground.tar之中。
tar结合find的方式创建很合适创建目录树或整个系统的增量备份。通过find查找比时间戳文件更新(newer)文件,可以创建在上一次归档之后出现的那些文件的归档,前提是每次创建归档之后立刻更新时间戳文件。
tar也能利用标准输入和标准输出。下面是一个综合示例:
find playground -name 'file-a' | tar cf - --files-from=- | gzip > playground.tgz
在本示例中,先用find得到匹配文件列表,然后通过管道将其表示为标准输入或标准输出。–files-from选项(也可以写为-T)时tar从文件中而不是从命令行中读取文件列表。最后,tar作为惯例,经过gzip压缩的tar归档采用.tgz作为扩展名,不过有时候也会用.tar.gz。
tar结合标准输入和标准输出的另一种值得注意的用法时在网络系统之间传输文件。假设有两台执行者类UNIX系统的计算机,各自安装了tar和ssh。在这种情况下,我们可以远程将远程主机(名为remote-sys)的目录传输至本地主机:
[me@linuxbox ~]$ mkdir remote-stuff
[me@linuxbox ~]$ cd remote-stuff
[me@linuxbox ~]$ ssh remote-sys ‘tar cf - Documents’ | tar xf -
me@remote-sys’s password:
[me@linuxbox remote-stuff]$ ls
Documents
这里,我们可以将远程主机remote-sys的Documents目录复制到本地主机的remote-stuff目录种。为了利用这一点,让tar生成归档(利用c模式),然后将其发送到标准输出,而不是生成文件(利用f选项加上-参数),这样就将归档通过ssh提供的加密隧道传输到了本地主机。在本地主机执行tar,提取(利用x模式)有标准输入提供的归档。
zip
zip既能压缩也能归档。该程序可以读写.zip文件Windows用户应该很熟悉这种文件格式,但在Linux中,gzip才是主流压缩程序,bzip2紧随其后。
zip基本用法如下:
zip options zipfile file... #压缩file...为zipfile
unzip zipfile #解压缩zipfile文件
要生成playground目录的zip归档,可以这样:
[me@linuxbox ~]$ zip -r playground.zip playground
除非加入用于递归操作的-r选项,否则只会保留playground目录(但不包含其内容)。尽管zip自动添加扩展名为.zip,但为了清晰起见,还是明确地写出扩展名。
在创建zip归档地归档地过程中,zip程序会显示一系列消息:
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文件地内容:
[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ unzip …/playground.zip
关于zip(与tar相反),如果指定地归档已存在,则将对其进行更新而不是替换。这意味这在保留现有归档的同时会向其中添加新文件,并替换同名文件。
在使用unzip时指定文件名,就可以有选择地列出和提取归档中地文件:
例如:
unzip -l playground.zip playground/dir-087/file-Z
Archive:../playground.zipLength Data Time Name------ ---- ---- ----0 10-05-18 9:25 playground/dir-087/file-Z----- ---- ---- ----0 1 file
-l选项使unzip只列出归档内容,但不从中提取文件。如果没有指定任何文件,unzip会列出归档中的所有文件。可以加入-v选项,显示更详细的信息
。
如果制定了-p(pipe, 管道)选项,unzip会将其输出结果发送到标准输出:
[me@linuxbox ~]$ unzip -p ls-etc.zip | less
zip和unzip的主要用途还是与Windows系统交换文件,而不是Linux中进行压缩和归档,tar和gzip则是这些任务的首选。
同步文件与目录
维护系统备份的常用策略包括保持一个或多个目录与本地主机(通常是某种可移动存储设备)或远程主机上的其它目录同步。例如,有一个尚处于开发阶段的网站备份,需要与其远程Web服务器上的实时副本进行同步。
在类UNIX系统中,执行该任务的首选工具rsync。它利用远程更新协议(rsync remove-update protocol)同步本地目录和远程目录,该协议快速检测两处目录之间的差异,执行使其达成同步所需的最少复制操作。因此,相较于其他复制程序,rsync速度飞快、经济实用。
rsync的用法如下:
rsync options source destination
其中,source和destination如下。
- 本地文件或目录
- 采用[user@]host:path形式指定的远程文件或目录。
- 采用rsync://[user@]host[:port]/path形式的URI指定的远程rsync服务器。
注意,source或destination必须有一个是本地的,rsync不支持远程对远程(remote-to-remote)复制。
将playground目录与其在foo目录中的副本进行同步:
rsync -av playground foo
加入了-a选项(用于归档,执行递归操作并保留文件属性)和-v选项(详细输出),在foo目录中制作playground目录的镜像(mirror)文件。在命令执行时,我们会看到被复制的文件和目录列表。显示类似于下面的汇总信息,说明复制了多少数据:
sent 135759 bytes received 57870 bytes 387258.00 bytes/sec
total size is 3230 speedup is 0.02
如果再次执行文件,会看到不同的结果:
building file list … done
sent 22635 bytes received 20 bytes 45310.00 bytes/sec
total size is 3230 speedup is 0.14
注意并灭有出现文件列表,这是因为rsync检测到~/playground和~/foo/playground之间并没有差异,无须复制任何文件。
在指定rsync的同步源的时候,有一个细微但却实用的特征,可以善加利用。考虑下面两个目录:
[me@linuxbox ~]$ ls
source destination
source目录中file1文件,destination目录为空。如果执行下列操作:
[me@linuxbox ~]$ rsync source destination
rsync会将source复制到destination:
[me@linuxbox ~]$ ls destination
source
在作为同步源的目录名称后加上/,rsync只会复制目录内容,而非目录本身:
[me@linuxbox ~]$ rsync source/ destination
[me@linuxbox ~]$ ls destination
file1
实用USB硬盘进行系统备份,硬盘接入系统被挂载在/media/BigDisk目录下,在硬盘上创建目录/backup,然后使用rsync命令将系统中重要的内容复制到其中,以此完成系统备份:
[me@linuxbox ~]$ mkdir /media/BIgDisk/backup
[me@linuxbox ~]$ sudo rsync -av --delete /etc /home /usr/local /media/BigDisk/backup
在本例中,系统中的/etc、/home、/usr/local目标被复制到硬盘中。添加了–delete选项,用于删除存在于备份设备,但源设备中已经不存在的文件(这一步在首次备份时并不重要,但在后续的复制操作中就会发挥作用了)。每次接入硬盘,首次执行rsync命令。如果使用别名的话会更方便。定义下列别名并将其添加到。bashrc文件中,以提供备份功能:
alias backup='sudo rsync -av --delete /etc /home /usr/local /media/BigDisk/backup'
在网络上使用rsync
rsync的真正美妙之处在于能够在网络上复制文件。rsync中的r就代表“remote”(远程)。远程复制有两种方法。第一种针对安装了rsync和远程Shell程序(例如ssh)的系统。假设局域网中还有另一个系统,其中尚有大量可用的硬盘空间,我们想使用该远程系统代替外置存储设备来执行备份操作。如果用来存放备份的/backup目录已经建好,可以这么做:
[me@linuxbox ~]$ suod rsync -av --delete --rsh=ssh /etc /home /usr/local remote-sys:/backup
命令做了两处改动,以便于网络复制。首先,加入了 --rsh=ssh选项,用于指示rsync使用ssh程序作为其远程Shell。这样就能使用加密隧道将本地数据安全地传输到远程系统。其次,在目标路径之前加入远程主机名(在本例中,远程主机名为remote-sys)。
第二种方法是使用了rsync服务器。可以配置rsync,使其作为守护进程执行,监听传入的同步请求。这种做法常用于实现远程系统监控。例如,Red Hat Software为其Fedora发行版的软件开发维护着一个大型仓库。对于软件测试人员来说,在系统发行版发布周期的测试阶段创建仓库哦的镜像文件非常有用。由于该仓库中的文件改动频繁(经常一天好几次),因此通过定期同步来维持本地镜像文件要比大批量复制仓库更可取。使用本地系统的rsync和远程的rsync服务器来创建镜像文件:
[me@linuxbox ~]$ mkdir fedora-devel
[me@linuxbox ~]$ rsync -av -delete rsync://archive.linux.duke.edu/fedora/linux/development/rawhide/Everything/x86_64/os/ fedora-devel
本例中用到了远程rsync服务器的URI,其组成包含协议(rsync://)、远程主机名(archive.linux.duke.edu)以及仓库的路径名。