The Linux Command Line-WILLIAM(11)-档案以及备份

309 阅读8分钟

可以定期备份来确保数据安全。可以使用多个程序用来管理文件集合。下面是文件压缩程序:

  • gzip —Compress or expand files.
  • bzip2 —A block sorting file compressor.

归档程序:

  • tar —Tape-archiving utility.
  • zip —Package and compress files.

文件同步程序:

  • rsync —Remote file and directory synchronization.

压缩文件

纵观计算机发展历史,一直在努力将最大的数据放入最小的可用空间,不管是 内存,硬盘或是网络带宽。包括现在的便携式音乐播放器,高清晰度电视,或者宽带上网,它们的存在归功于有效的数据压缩技术。

数据压缩是从数据中移除冗余的过程。例如,假设我们有一个全黑的图片文件,其尺寸为100*100像素。(假设每像素为24bits,或者3 bytes)因此所占存储空间 100 × 100 × 3 = 30,000.

这个只有一个颜色的图片包含完全冗余的数据。我们可以对数据进行编码为我们有一块 30,000 黑像素。因此,相比于存储包含30,000个零的数据块(黑色为0)可以将其压缩为为一个数字30,000 后面跟上 0 。 此数据压缩方案为 run-length encoding,是最基本的压缩技术其中之一。今天的技术更加先进以及复杂,但是其根本目标是一致的——减少冗余数据。

压缩算法(用于执行压缩的数学技术)分为两大类,lossless 和 lossy。 Lossless可保留原始文件中包含的所有数据。这意味着当文件从压缩的版本恢复时,恢复文件与未压缩源文件完全一样。另一方面,Lossy 压缩会在执行压缩时删除数据,来应用更多压缩。恢复损失文件后,它与原始版本不匹配; 相反,它是一个近似值。例如 JPEG 格式图片,MP3 格式音乐。因为在计算级上的大量数据无法忍受数据损失,接下来我们看下无损压缩:

gzip—Compress or Expand Files

gzip 程序用来压缩一个或者多个文件。 当执行程序时,它替换原文件为将原文件压缩的文件。相对应的 gunzip 程序用来还原压缩文件为原来文件:

[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 文件,内容为 /etc 下的列表,接下来执行 gzip 将文件压缩,接下里查看压缩文件,可以看到压缩文件为原来的大约五分之一以及相同的权限以及时间戳。

接下来使用 gunzip 程序来解压文件,接下来看解压后文件具有相同的权限以及时间戳。

Table 18-1: gzip Options

OptionDescription
-cWrite output to standard output and keep original files. May also be specified with --stdout and --to-stdout .
-dDecompress. This causes gzip to act like gunzip . May also be specified with --decompress or --uncompress
-fForce compression even if a compressed version of the original file already exists. May also be specified with --force
-hDisplay usage information. May also be specified with --help
-lList compression statistics for each file compressed. May also be specified with --list
-rIf one or more arguments on the command line are directories, recursively compress files contained within them. May also be specified with --recursive
-tTest the integrity of a compressed file. May also be specified with --test .
-vDisplay verbose messages while compressing. May also be specified with --verbose
-numberSet amount of compression. number is an integer in the range of 1 (fastest, least compression) to 9 (slowest, most compression). The values 1 and 9 may also be expressed as --fast and --best , respectively. The default value is 6.

让我们看下早些时候的例子:

[me@linuxbox ~]$ gzip foo.txt
[me@linuxbox ~]$ gzip -tv foo.txt.gz
foo.txt.gz: OK
[me@linuxbox ~]$ gzip -d foo.txt.gz

上面代码在压缩文件后,我们使用 -t 以及 -v 选项来测试压缩文件完整性,最后,将压缩文件还原。

gzip 也可用来使用标准输入,输出:

[me@linuxbox ~]$ ls -l /etc | gzip > foo.txt.gz

gunzip 程序(用来解压 gzip 文件)假设文件名称以 .gz 扩展名结束,因此,只要指定名称不与存在的为压缩文件有冲突,就没必要来指定它

[me@linuxbox ~]$ gunzip foo.txt

如果只是想要查看压缩文件内容,可以使用下面 命令:

[me@linuxbox ~]$ gunzip -c foo.txt | less

另外,名为 zcat 也支持 gzip,相当于 gunzip 与 -c 选项。可以像 使用 cat 命令 一样对 gzip 压缩文件使用。

[me@linuxbox ~]$ zcat foo.txt.gz | less

【注】也存在 zless 程序,它执行与上述管道相同的功能。

bzip2—Higher Compression at the Cost of Speed

Julian Seward 的 bzip2 程序类似于gzip,但是使用不同压缩算法,从而以压缩速度为代价实现更高级别的压缩。在大多数方面,它的工作方式与gzip相同。使用 bzip2 压缩的文件 以 .bz2扩展名 表示:

[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.txt.bz2

可以看到,bzip2 与 gzip 可以使用相同的方法。上面的所有gzip的选项(除了 -r)都支持 bzip2 。

bunzip2 和 bzcat 可以用来解压 bzip2 文件。 bzip2还附带了bzip2recover程序,该程序将尝试恢复损坏的.bz2文件。

【注】压缩层次选项(-number)与 bzip2 有不同的含义。

DON’T BE COMPRESSIVE COMPULSIVE

经常看到有人试图压缩 已经使用有效算法压缩过的文件,例如:

$ gzip picture.jpg

这样做只会浪费时间与空间!如果压缩 已经算法压缩过的文件,实际上会得到一个较大的文件,这是因为所有压缩技术都涉及一些附加开销,这些开销被添加到文件中以描述压缩。如果试图压缩一个已经不包含冗余信息的文件,那么压缩将无法节省任何资源来抵消额外的开销。

Archiving Files

与压缩结合使用的常见文件管理任务是归档。归档是一个收集许多文件并将它们打包成一个大文件的过程。归档通常是系统备份的一部分。通常在旧数据从系统中移动到长期存储硬盘中使用。

tar—Tape Archiving Utility

在类Unix软件中,tar 程序 是归档经典工具。为 tape archive 的缩写。揭示作为备份磁带的工具的根源。虽然它仍然用来传统作业,但是同样在别的设备上表现很好。经常会看到 .tar 或者 .tgz 的扩展名,分别指 “完全的” tar archive 和 gzip 的 archive。tar archive 可以由 单独的文件,一个文件夹以及子文件夹,或者 二者的混合,命令模式如下:

tar mode[options] pathname...

mode 在下表中的操作模式(一部分列表,查看 man page 获取完整版):

Table 18-2: tar Modes

ModeDescription
cCreate an archive from a list of files and/or directories.
xExtract an archive.
rAppend specified pathnames to the end of an archive.
tList the contents of an archive.

首先,创建文件夹 playground

[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 归档:

[me@linuxbox ~]$ tar cf playground.tar playground

此命令创建 playground.tar 包含了整个 playground 文件夹内容。用于指定tar归档文件名称的mode和f选项可以结合在一起,并且不需要前划线。并且 模式必须在任何其他选项前面:

列出 tar 中的内容:

[me@linuxbox ~]$ tar tf playground.tar

加 v(verbose) 显示细节

[me@linuxbox ~]$ tar tvf playground.tar

在不同的位置 提取 playground 中文件:

[me@linuxbox ~]$ mkdir foo
[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ tar xf ../playground.tar
[me@linuxbox foo]$ ls
playground

除非使用超级用户进行操作,不然从存档中提取的文件和目录将由执行复原的用户拥有,而不是原来的所有者。

tar 处理文件路径默认使用相对路径。tar通过在创建归档文件时简单地从路径名中删除前导斜杠来实现此目的:

[me@linuxbox foo]$ cd ~
[me@linuxbox ~]$ tar cf playground2.tar ~/playground

【注】再按下回车时候 ~/playground 将会被扩展成 /home/me/playground 接下来,提取文件:

[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ tar xf ../playground2.tar
[me@linuxbox foo]$ ls
home playground
[me@linuxbox foo]$ ls home
me
[me@linuxbox foo]$ ls home/me
playground

可以看到当提取文件时候,在当前目录下重新创建了 home/me/playground ,这使得我们可以在任何目录下提取文件。

假设我们想要拷贝 /home 文件夹 到大容量 USB硬盘(自动挂载在 /media 文件夹下)假设在附加磁盘时,磁盘的卷名为BigDisk。 制作tar:

[me@linuxbox ~]$ sudo tar cf /media/BigDisk/home.tar /home

卸载 USB硬盘 后,将其连接到另一台电脑(再次装载到/media/BigDisk),提取文件:

[me@linuxbox2 ~]$ cd /
[me@linuxbox2 /]$ sudo tar xf /media/BigDisk/home.tar

上面命令首先改变目录到 / ,如此以来 提取文件对 根目录就为相对的路径。

当提取文件时候可以指定文件:

tar xf archive.tar pathname

路径名必须是 tar 中存储的完整的,相对路径名。指定路径名时候,通配符不能正常使用,然而,GNU 版本的 tar 可以用 --wildcards 选项来支持通配符:

[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ tar xf ../playground2.tar --wildcards 'home/me/playground/
dir-*/file-A'

tar 也经常与 find 来连用来创建tar,例如,使用 find 来创建 tar:

[me@linuxbox ~]$ find playground -name 'file-A' -exec tar rf playground.tar '{}' '+'

首先查找所有 playground 中 file-A 文件,接着执行 -exec,以 附加模式(r) 唤起 tar 来将文件附加到 playground.tar.

将 find 与 tar 连用 一个场景是 在整个系统或文件夹树中创建增量备份。通过 fin 发现新版文件,然后创建 tar。

tar 可以使用标准输入输出:

[me@linuxbox foo]$ cd ~
[me@linuxbox ~]$ find playground -name 'file-A' | tar cf - --files-from=- | gzip
> playground.tgz

上面例子,我们使用 find 程序来创建 匹配文件列表,将其用管道输送到 tar。如果指定了文件名-,则根据需要将其视为标准输入或输出(使用-表示标准输入/输出的约定也被许多其他程序使用),--files-from 选项(也可以为 -T)使tar从文件而不是从命令行读取其路径名列表。最后,创建的 tar 用管道被输送到 gzip 来创建 压缩的 playground.tgz。.tgz扩展名是gzip压缩的tar文件的常规扩展名;有时也使用扩展名.tar.gz。

虽然在上面使用了额外的程序来压缩,但是现在的 GNU 版本的 tar 也提供 z 与 j选项来支持 gzip 与 bzip2 方式直接压缩,可以通过以下方式简化上面命令:

[me@linuxbox ~]$ find playground -name 'file-A' | tar czf playground.tgz -T -

bzip2 压缩:

[me@linuxbox ~]$ find playground -name 'file-A' | tar cjf playground.tbz -T -

通过改变选项 z 和 j 来改变压缩方式(并改变输出扩展名, .tbz 指 bzip2压缩)

通过网络在系统之间传输文件,tar 也可以使用标准输入输出。从远程主机 转移文件夹到本地:

[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

上面命令直接从远程主机remote-sys中 拷贝 Documents 文件夹 到本地 remote-stuff 文件夹中。

首先使用 运行 ssh 来远程执行命令 并且 在本地“观察”执行结果——为了在本地看到结果,远程主机将其标准输出发送到本地。可以利用这一点通过 创建(c模式) tar并将其发送到 标准输出,而不是文件(带有 破折号 参数的f选项)。在本地系统上,执行tar并使其扩展为从标准输入提供的归档文件(x模式)。

zip—Package and Compress Files

zip程序既是压缩工具又是存档器。用于程序的文件格式为 Windows 用户熟悉的.zip,。在Linux中 常用的压缩程序为 gzip,第二是 bzip2。Linux用户相比于用来执行压缩与归档,主要用 zip 与Windows系统 来交换数据

使用下面命令格式来使用 zip

zip options zipfile file...

创建 zip 归档文件:

[me@linuxbox ~]$ zip -r playground.zip playground

除非指定 -r 选项(递归遍历),否则只有 playground 文件夹(不包括其内容)被存储。扩展名.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 提取文件:

[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ unzip ../playground.zip

值得注意的是,与 tar 相反,如果指定已经存在的归档文件,则将对其进行更新而不是替换。这意味着将保留现有的存档,但是会添加新文件并替换匹配的文件。

可以列出文件并有选择地从zip存档中提取文件:

[me@linuxbox ~]$ unzip -l playground.zip playground/dir-087/file-Z
Archive: ./playground.zip
Length Date Time Name
-------- ---- ---- ----
0 10-05-12 09:25 playground/dir-087/file-Z
-------- -------
0 1 file
[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ unzip ../playground.zip playground/dir-087/file-Z
Archive: ../playground.zip
replace playground/dir-087/file-Z? [y]es, [n]o, [A]ll, [N]one, [r]ename: y
extracting: playground/dir-087/file-Z

使用 -l 选项使得 unzip 不解压文件而是仅仅显示其中文件。如果未指定文件则显示所有文件, -v 选项可以显示详细信息。在解压时候,如果文件冲突,会提示用户是否替换。

像tar一样,zip可以利用标准的输入和输出。 可以通过-@选项通过管道传递要压缩的文件名列表:

[me@linuxbox foo]$ cd
[me@linuxbox ~]$ find playground -name "file-A" | zip -@ file-A.zip

zip还支持将其输出写入标准输出,不幸的是,unzip 程序不接受标准输入。这样使得zip和unzip不能像tar一样执行网络文件复制。

zip可以接受标准输入,因此可以用于压缩其他程序的输出文件名:

[me@linuxbox ~]$ ls -l /etc/ | zip ls-etc.zip -
adding: - (deflated 80%)

当指定-p(用于管道)选项时,unzip程序允许将其输出发送到标准输出:

[me@linuxbox ~]$ unzip -p ls-etc.zip | less

Synchronizing Files and Directories

维护一个系统的备份的常用策略包括 同步一个或者多个文件夹到本地(或者可移除设备等)的另外文件夹。例如,有一个开发中的网站的备份,并不时将其与远程Web服务器上的“实时”副本同步。

rsync—Remote File and Directory Synchronization

rsync 可以执行这个任务,此程序通过 rsync remote- update protocol 协议可以同步本地以及远程主机文件夹,此协议可以快速检测两个文件夹的差异并执行使它们同步所需的最少复制量。相比于其他类型的复制程序,这使 rsync 可以非常快速且经济地使用。命令格式:

rsync options source destination

其中 source 和 destination 分别是下面情况其中一个:

  • A local file or directory
  • A remote file or directory in the form of [user@]host:path
  • A remote rsync server specified with a URI of rsync://[user@]host[:port]/path

source 或者 destination 必须有一个是 本地文件,不支持Remote-to-remote 复制。

我们可以对一些本地文件使用 rsync ,首先,清空 foo 文件夹:

[me@linuxbox ~]$ rm -rf foo/*

接下来,把Playground目录与foo中的相应副本同步:

[me@linuxbox ~]$ rsync -av playground foo

-a 选项(archiving—递归和保留文件属性)以及 -v 选项(详细输出)。命令执行之后,将会看到文件列表将会被复制。最后,将会看到汇总信息如下所示:

sent 135759 bytes received 57870 bytes 387258.00 bytes/sec
total size is 3230 speedup is 0.02

如果再次运行命令:

[me@linuxbox ~]$ rsync -av playgound foo
building file list ... done
sent 22635 bytes received 20 bytes 45310.00 bytes/sec
total size is 3230 speedup is 0.14

这一这次并没有文件列表。这是因为 rsync 未检测到差异,如果在 playground 中修改文件再次运行命令:

[me@linuxbox ~]$ touch playground/dir-099/file-Z
[me@linuxbox ~]$ rsync -av playground foo
building file list ... done
playground/dir-099/file-Z
sent 22685 bytes received 42 bytes 45454.00 bytes/sec
total size is 3230 speedup is 0.14

如果将存储设备连接到系统,挂载于 /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 文件夹 到存储设备中:

alias backup='sudo rsync -av --delete /etc /home /usr/local /media/BigDisk/backup'

Using rsync over a Network

rsync 的真正优点之一是它可用于通过网络复制文件。rsync 的 r 的含义为 remote 。远程复制可以有两种方式完成

第一种方式要另外一个也安装了 rsync 程序的系统和远程shell程序(如ssh)。假设 想要复制到远程服务器,假设已经有 /backup 文件夹:

[me@linuxbox ~]$ sudo rsync -av --delete --rsh=ssh /etc /home /usr/local remote-
sys:/backup

上面命令为了实现网络复制有两处改变。首先,增加了 --rsh=ssh 选项,使得 rsync 使用 ssh 程序作为远程 shell工具,因此可以使用 SSH 加密的信道来传输数据到远程主机。接着,我们通过将远程主机的名称(在本例中远程主机命名为remote-sys)作为目标路径名的前缀来指定远程主机。

第二种方式通过 rysnc server。rsync 可以配置为守护进程并监听请求同步请求。这通常是为了对远程系统进行镜像。例如,红帽为其Fedora发行版维护着一个正在开发的软件包的大型存储库。对于软件测试人员来说,在发行版本周期的测试阶段 映射 这个集合是很有用的。因为在仓库中文件经常变化,相比于复制仓库,通过定期同步来维护本地镜像是理想的。其中一个仓库就在 Georgia Tech;我们可以像这样使用我们本地的rsync和Georgia Tech的rsync服务器来镜像它

[me@linuxbox ~]$ mkdir fedora-devel
[me@linuxbox ~]$ rsync -av -delete rsync://rsync.gtlib.gatech.edu/fedora-
linux-core/development/i386/os fedora-devel

上面命令中,我们使用远程 rsync 服务的 URI,它由协议头(rsync://),以及 远程主机名(rsync.gtlib.gatech.edu),最后 为仓库的路径。