Linux学习笔记18——压缩文件的用途与技术、Linux 系统常见的压缩指令、打包指令: tar

一、压缩文件的用途与技术

你是否有过文件文件太大,导致无法以正常的 email 方式发送出去 (很多 email 都有容量大约 25MB 每封信的限制啊!)? 又或者学校、厂商要求使用 CD 或 DVD 来传递归档用的数据,但是你的单一文件却都比这些传统的一次性储存媒体还要大!那怎么分成多片来烧录呢? 还有,你是否有过要备份某些重要数据,偏偏这些数据量太大了,耗掉了你很多的磁盘空间呢? 这个时候,那个好用的“文件压缩”技术可就派的上用场了!

因为这些比较大型的文件通过所谓的文件压缩技术之后,可以将他的磁盘使用量降低,可以达到减低文件大小的效果。此外,有的压缩程序还可以进行容量限制, 使一个大型文件可以分区成为数个小型文件,以方便软盘片携带呢!

那么什么是“文件压缩”呢?我们来稍微谈一谈他的原理好了。目前我们使用的计算机系统中都是使用所谓的 Bytes 单位来计量的!不过,事实上,计算机最小的计量单位应该是 bits 才对啊。此外,我们也知道 1 Byte = 8 bits 。但是如果今天我们只是记忆一个数字,亦即是 1 这个数字呢?他会如何记录?假设一个 Byte 可以看成下面的模样:

□□□□□□□□

Tips 由于 1 Byte = 8 bits ,所以每个 Byte 当中会有 8 个空格,而每个空格可以是 0, 1 ,这里仅是做为一个约略的介绍, 更多的详细数据请参考第零章的计算机概论吧!

由于我们记录数字是 1 ,考虑计算机所谓的二进制喔,如此一来, 1 会在最右边占据 1 个 bit,而其他的 7 个 bits 将会自动的被填上 0 啰!你看看,其实在这样的例子中,那 7 个 bits 应该是“空的”才对!不过,为了要满足目前我们的操作系统数据的存取,所以就会将该数据转为Byte 的型态来记录了!而一些聪明的计算机工程师就利用一些复杂的计算方式, 将这些没有使用到的空间“丢”出来,以让文件占用的空间变小!这就是压缩的技术啦!

另外一种压缩技术也很有趣,他是将重复的数据进行统计记录的。举例来说,如果你的数据为“111....”共有100个1时, 那么压缩技术会记录为“100个1”而不是真的有100个1的位存在!这样也能够精简文件记录的容量呢! 非常有趣吧!

简单的说,你可以将他想成,其实文件里面有相当多的“空间”存在,并不是完全填满的,而“压缩”的技术就是将这些“空间”填满,以让整个文件占用的容量下降! 不过,这些“压缩过的文件”并无法直接被我们的操作系统所使用的,因此, 若要使用这些被压缩过的文件数据,则必须将他“还原”回来未压缩前的模样, 那就是所谓的“解压缩”啰!而至于压缩后与压缩的文件所占用的磁盘空间大小, 就可以被称为是“压缩比”啰!更多的技术文件或许你可以参考一下:

RFC 1952 文件:http://www.ietf.org/rfc/rfc1952.txt

鸟哥站上的备份:http://linux.vbird.org/linux_basic/0240tarcompress/0240tarcompress_gzip.php

这个“压缩”与“解压缩”的动作有什么好处呢?最大的好处就是压缩过的文件大小变小了, 所以你的硬盘容量无形之中就可以容纳更多的数据。此外,在一些网络数据的传输中,也会由于数据量的降低, 好让网络带宽可以用来作更多的工作!而不是老是卡在一些大型的文件传输上面呢!目前很多的 WWW 网站也是利用文件压缩的技术来进行数据的传送,好让网站带宽的可利用率上升喔!

Tips 上述的WWW网站压缩技术蛮有趣的!他让你网站上面“看的到的数据”在经过网络传输时,使用的是“压缩过的数据”, 等到这些压缩过的数据到达你的计算机主机时,再进行解压缩,由于目前的计算机运算速度相当的快速, 因此其实在网页浏览的时候,时间都是花在“数据的传输”上面,而不是 CPU 的运算啦!如此一来,由于压缩过的数据量降低了,自然传送的速度就会增快不少!

若你是一位软件工程师,那么相信你也会喜欢将你自己的软件压缩之后提供大家下载来使用, 毕竟没有人喜欢自己的网站天天都是带宽满载的吧?举个例子来说, Linux 3.10.81(CentOS 7 用的延伸版本) 完整的核心大小约有 570 MB 左右,而由于核心主要多是 ASCIIcode 的纯文本体态文件,这种文件的“多余空间”最多了。而一个提供下载的压缩过的 3.10.81核心大约仅有 76MB 左右,差了几倍呢?你可以自己算一算喔!

二、Linux 系统常见的压缩指令

在Linux的环境中,压缩文件的扩展名大多是:“.tar, .tar.gz, .tgz, .gz, .Z, .bz2, *.xz”,为什么会有这样的扩展名呢?不是说 Linux 的扩展名没有什么作用吗?

这是因为 Linux 支持的压缩指令非常多,且不同的指令所用的压缩技术并不相同,当然彼此之间可能就无法互通压缩/解压缩文件啰。 所以,当你下载到某个压缩文件时,自然就需要知道该文件是由哪种压缩指令所制作出来的,好用来对照着解压缩啊! 也就是说,虽然 Linux文件的属性基本上是与文件名没有绝对关系的, 但是为了帮助我们人类小小的脑袋瓜子,所以适当的扩展名还是必要的! 下面我们就列出几个常见的压缩文件扩展名吧:

*.Z compress 程序压缩的文件;

*.zip zip 程序压缩的文件;

*.gz gzip 程序压缩的文件;

*.bz2 bzip2 程序压缩的文件;

*.xz xz 程序压缩的文件;

*.tar tar 程序打包的数据,并没有压缩过;

*.tar.gz tar 程序打包的文件,其中并且经过 gzip 的压缩

*.tar.bz2 tar 程序打包的文件,其中并且经过 bzip2 的压缩

*.tar.xz tar 程序打包的文件,其中并且经过 xz 的压缩

Linux上常见的压缩指令就是 gzip, bzip2 以及最新的 xz ,至于 compress 已经退流行了。为了支持 windows 常见的 zip,其实 Linux 也早就有 zip 指令了! gzip 是由 GNU 计划所开发出来的压缩指令,该指令已经取代了 compress 。 后来 GNU 又开发出 bzip2 及 xz 这几个压缩比更好的压缩指令!不过,这些指令通常仅能针对一个文件来压缩与解压缩,如此一来, 每次压缩与解压缩都要一大堆文件,岂不烦人?此时,那个所谓的“打包软件, tar”就显的很重要啦!

这个 tar 可以将很多文件“打包”成为一个文件!甚至是目录也可以这么玩。不过,单纯的 tar功能仅是“打包”而已,亦即是将很多文件集结成为一个文件, 事实上,他并没有提供压缩的功能,后来,GNU 计划中,将整个 tar 与压缩的功能结合在一起,如此一来提供使用者更方便并且更强大的压缩与打包功能! 下面我们就来谈一谈这些在 Linux 下面基本的压缩指令吧!

1, gzip, zcat/zmore/zless/zgrep

gzip 可以说是应用度最广的压缩指令了!目前 gzip 可以解开 compress, zip 与 gzip 等软件所压缩的文件。 至于 gzip 所创建的压缩文件为 *.gz 的文件名喔!让我们来看看这个指令的语法吧:

[dmtsai@study ~]$ gzip [-cdtv#] 文件名

[dmtsai@study ~]$ zcat 文件名.gz

选项与参数:

-c :将压缩的数据输出到屏幕上,可通过数据流重导向来处理;

-d :解压缩的参数;

-t :可以用来检验一个压缩文件的一致性~看看文件有无错误;

-v :可以显示出原文件/压缩文件的压缩比等信息;

-# :# 为数字的意思,代表压缩等级,-1 最快,但是压缩比最差、-9 最慢,但是压缩比最好!默认是 -6

范例一:找出 /etc 下面 (不含子目录) 容量最大的文件,并将它复制到 /tmp ,然后以 gzip 压缩

[dmtsai@study ~]$ ls -ldSr /etc/* # 忘记选项意义?请自行 man 啰!

.....(前面省略).....

-rw-r--r--. 1 root root 25213 Jun 10 2014 /etc/dnsmasq.conf

-rw-r--r--. 1 root root 69768 May 4 17:55 /etc/ld.so.cache

-rw-r--r--. 1 root root 670293 Jun 7 2013 /etc/services

[dmtsai@study ~]$ cd /tmp

[dmtsai@study tmp]$ cp /etc/services .

[dmtsai@study tmp]$ gzip -v services

services: 79.7% -- replaced with services.gz

[dmtsai@study tmp]$ ll /etc/services /tmp/services*

-rw-r--r--. 1 root root 670293 Jun 7 2013 /etc/services

-rw-r--r--. 1 dmtsai dmtsai 136088 Jun 30 18:40 /tmp/services.gz

当你使用 gzip 进行压缩时,在默认的状态下原本的文件会被压缩成为 .gz 的文件名,原始文件就不再存在了。 这点与一般习惯使用 windows 做压缩的朋友所熟悉的情况不同喔!要注意!要注意! 此外,使用 gzip 压缩的文件在 Windows 系统中,竟然可以被 WinRAR/7zip 这个软件解压缩呢!很好用吧!至于其他的用法如下:

范例二:由于 services 是文本文件,请将范例一的压缩文件的内容读出来!

[dmtsai@study tmp]$ zcat services.gz

# 由于 services 这个原本的文件是是文本文件,因此我们可以尝试使用 zcat/zmore/zless 去读取!

# 此时屏幕上会显示 servcies.gz 解压缩之后的原始文件内容!

范例三:将范例一的文件解压缩

[dmtsai@study tmp]$ gzip -d services.gz

# 鸟哥不要使用 gunzip 这个指令,不好背!使用 gzip -d 来进行解压缩!

# 与 gzip 相反, gzip -d 会将原本的 .gz 删除,回复到原本的 services 文件。

范例四:将范例三解开的 services 用最佳的压缩比压缩,并保留原本的文件

[dmtsai@study tmp]$ gzip -9 -c services > services.gz

范例五:由范例四再次创建的 services.gz 中,找出 http 这个关键字在哪几行?

[dmtsai@study tmp]$ zgrep -n 'http' services.gz

14:# http://www.iana.org/assignments/port-numbers

89:http 80/tcp www www-http # WorldWideWeb HTTP

90:http 80/udp www www-http # HyperText Transfer Protocol

.....(下面省略).....

其实 gzip 的压缩已经最优化过了,所以虽然 gzip 提供 1~9 的压缩等级,不过使用默认的 6就非常好用了! 因此上述的范例四可以不要加入那个 -9 的选项。范例四的重点在那个 -c 与> 的使用啰!-c 可以将原本要转成压缩文件的数据内容,将它变成文字类型从屏幕输出, 然后我们可以通过大于 (>) 这个符号,将原本应该由屏幕输出的数据,转成输出到文件而不是屏幕,所以就能够创建出压缩挡了。只是文件名也要自己写, 当然最好还是遵循 gzip 的压缩文件名要求较佳喔!!更多的 > 这个符号的应用,我们会在 bash 章节再次提及!

cat/more/less 可以使用不同的方式来读取纯文本文件,那个 zcat/zmore/zless 则可以对应于cat/more/less 的方式来读取纯文本文件被压缩后的压缩文件! 由于 gzip 这个压缩指令主要想要用来取代 compress 的,所以不但 compress 的压缩文件可以使用 gzip 来解开,同时 zcat这个指令可以同时读取 compress 与 gzip 的压缩文件呦!

另外,如果你还想要从文字压缩文件当中找数据的话,可以通过 egrep 来搜寻关键字喔!而不需要将压缩文件解开才以 grep 进行! 这对查询备份中的文本文件数据相当有用!

Tips 时至今日,应该也没有人爱用 compress 这个老老的指令了!因此,这一章已经拿掉了compress 的介绍~而如果你还有备份数据使用的是 compress 创建出来的 .Z 文件,那也无须担心,使用 znew 可以将该文件转成 gzip 的格示喔!

2,bzip2, bzcat/bzmore/bzless/bzgrep

若说 gzip 是为了取代 compress 并提供更好的压缩比而成立的,那么 bzip2 则是为了取代gzip 并提供更佳的压缩比而来的。 bzip2 真是很不错用的东西~这玩意的压缩比竟然比 gzip还要好~至于 bzip2 的用法几乎与 gzip 相同!看看下面的用法吧!

[dmtsai@study ~]$ bzip2 [-cdkzv#] 文件名

[dmtsai@study ~]$ bzcat 文件名.bz2

选项与参数:

-c :将压缩的过程产生的数据输出到屏幕上!

-d :解压缩的参数

-k :保留原始文件,而不会删除原始的文件喔!

-z :压缩的参数 (默认值,可以不加)

-v :可以显示出原文件/压缩文件的压缩比等信息;

-# :与 gzip 同样的,都是在计算压缩比的参数, -9 最佳, -1 最快!

范例一:将刚刚 gzip 范例留下来的 /tmp/services 以 bzip2 压缩

[dmtsai@study tmp]$ bzip2 -v services

services: 5.409:1, 1.479 bits/Byte, 81.51% saved, 670293 in, 123932 out.

[dmtsai@study tmp]$ ls -l services*

-rw-r--r--. 1 dmtsai dmtsai 123932 Jun 30 18:40 services.bz2

-rw-rw-r--. 1 dmtsai dmtsai 135489 Jun 30 18:46 services.gz

# 此时 services 会变成 services.bz2 之外,你也可以发现 bzip2 的压缩比要较 gzip 好喔!!

# 压缩率由 gzip 的 79% 提升到 bzip2 的 81% 哩!

范例二:将范例一的文件内容读出来!

[dmtsai@study tmp]$ bzcat services.bz2

范例三:将范例一的文件解压缩

[dmtsai@study tmp]$ bzip2 -d services.bz2

范例四:将范例三解开的 services 用最佳的压缩比压缩,并保留原本的文件

[dmtsai@study tmp]$ bzip2 -9 -c services > services.bz2

看上面的范例,你会发现到 bzip2 连选项与参数都跟 gzip 一模一样!只是扩展名由 .gz 变成.bz2 而已!其他的用法都大同小异,所以鸟哥就不一一介绍了! 你也可以发现到 bzip2 的压缩率确实比 gzip 要好些!不过,对于大容量文件来说,bzip2 压缩时间会花比较久喔!至少比 gzip 要久的多! 这没办法~要有更多可用容量,就得要花费相对应的时间!还 OK 啊!

3,xz, xzcat/xzmore/xzless/xzgrep

虽然 bzip2 已经具有很棒的压缩比,不过显然某些自由软件开发者还不满足,因此后来还推出了 xz 这个压缩比更高的软件!这个软件的用法也跟 gzip/bzip2 几乎一模一样! 那我们就来瞧一瞧!

[dmtsai@study ~]$ xz [-dtlkc#] 文件名

[dmtsai@study ~]$ xcat 文件名.xz

选项与参数:

-d :就是解压缩啊!

-t :测试压缩文件的完整性,看有没有错误

-l :列出压缩文件的相关信息

-k :保留原本的文件不删除~

-c :同样的,就是将数据由屏幕上输出的意思!

-# :同样的,也有较佳的压缩比的意思!

范例一:将刚刚由 bzip2 所遗留下来的 /tmp/services 通过 xz 来压缩!

[dmtsai@study tmp]$ xz -v services

services (1/1)

100 % 97.3 KiB / 654.6 KiB = 0.149

[dmtsai@study tmp]$ ls -l services*

-rw-rw-r--. 1 dmtsai dmtsai 123932 Jun 30 19:09 services.bz2

-rw-rw-r--. 1 dmtsai dmtsai 135489 Jun 30 18:46 services.gz

-rw-r--r--. 1 dmtsai dmtsai 99608 Jun 30 18:40 services.xz

# 各位观众!看到没有啊!!容量又进一步下降的更多耶!好棒的压缩比!

范例二:列出这个压缩文件的信息,然后读出这个压缩文件的内容

[dmtsai@study tmp]$ xz -l services.xz

Strms Blocks Compressed Uncompressed Ratio Check Filename

1 1 97.3 KiB 654.6 KiB 0.149 CRC64 services.xz

# 竟然可以列出这个文件的压缩前后的容量,真是太人性化了!这样观察就方便多了!

[dmtsai@study tmp]$ xzcat services.xz

范例三:将他解压缩吧!

[dmtsai@study tmp]$ xz -d services.xz

范例四:保留原文件的文件名,并且创建压缩文件!

[dmtsai@study tmp]$ xz -k services

虽然 xz 这个压缩比真的好太多太多了!以鸟哥选择的这个 services 文件为范例,他可以将gzip 压缩比 (压缩后/压缩前) 的 21% 更进一步优化到 15% 耶! 差非常非常多!不过, xz最大的问题是...时间花太久了!如果你曾经使用过 xz 的话,应该会有发现,他的运算时间真的比 gzip 久很多喔!

鸟哥以自己的系统,通过“ time [gzip|bzip2|xz] -c services > services.[gz|bz2|xz] ”去执行运算结果,结果发现这三个指令的执行时间依序是: 0.019s, 0.042s, 0.261s, 看最后一个数字!差了 10 倍的时间耶!所以,如果你并不觉得时间是你的成本考虑,那么使用 xz 会比较好!如果时间是你的重要成本,那么 gzip 恐怕是比较适合的压缩软件喔!

三、打包指令: tar

前一小节谈到的指令大多仅能针对单一文件来进行压缩,虽然 gzip, bzip2, xz 也能够针对目录来进行压缩,不过, 这两个指令对目录的压缩指的是“将目录内的所有文件 "分别" 进行压缩”的动作!而不像在 Windows 的系统,可以使用类似 WinRAR 这一类的压缩软件来将好多数据“包成一个文件”的样式。

这种将多个文件或目录包成一个大文件的指令功能,我们可以称呼他是一种“打包指令”啦!那 Linux 有没有这种打包指令呢?是有的!那就是鼎鼎大名的 tar 这个玩意儿了! tar 可以将多个目录或文件打包成一个大文件,同时还可以通过 gzip/bzip2/xz 的支持,将该文件同时进行压缩! 更有趣的是,由于 tar 的使用太广泛了,目前 Windows 的 WinRAR 也支持 .tar.gz文件名的解压缩呢! 很不错吧!所以下面我们就来玩一玩这个咚咚!

1,tar

tar 的选项与参数非常的多!我们只讲几个常用的选项,更多选项您可以自行 man tar 查询啰!

[dmtsai@study ~]$ tar [-z|-j|-J] [cv] [-f 待创建的新文件名] filename... <==打包与压缩

[dmtsai@study ~]$ tar [-z|-j|-J] [tv] [-f 既有的 tar文件名] <==察看文件名

[dmtsai@study ~]$ tar [-z|-j|-J] [xv] [-f 既有的 tar文件名] [-C 目录] <==解压缩

选项与参数:

-c :创建打包文件,可搭配 -v 来察看过程中被打包的文件名(filename)

-t :察看打包文件的内容含有哪些文件名,重点在察看“文件名”就是了;

-x :解打包或解压缩的功能,可以搭配 -C (大写) 在特定目录解开

特别留意的是, -c, -t, -x 不可同时出现在一串命令行中。

-z :通过 gzip 的支持进行压缩/解压缩:此时文件名最好为 *.tar.gz

-j :通过 bzip2 的支持进行压缩/解压缩:此时文件名最好为 *.tar.bz2

-J :通过 xz 的支持进行压缩/解压缩:此时文件名最好为 *.tar.xz

特别留意, -z, -j, -J 不可以同时出现在一串命令行中

-v :在压缩/解压缩的过程中,将正在处理的文件名显示出来!

-f filename:-f 后面要立刻接要被处理的文件名!建议 -f 单独写一个选项啰!(比较不会忘记)

-C 目录 :这个选项用在解压缩,若要在特定目录解压缩,可以使用这个选项。

其他后续练习会使用到的选项介绍:

-p(小写) :保留备份数据的原本权限与属性,常用于备份(-c)重要的配置文件

-P(大写) :保留绝对路径,亦即允许备份数据中含有根目录存在之意;

--exclude=FILE:在压缩的过程中,不要将 FILE 打包!

其实最简单的使用 tar 就只要记忆下面的方式即可:

压 缩:tar -j<u>c</u>v -f filename.tar.bz2 要被压缩的文件或目录名称

查 询:tar -j<u>t</u>v -f filename.tar.bz2

解压缩:tar -j<u>x</u>v -f filename.tar.bz2 -C 欲解压缩的目录

那个 filename.tar.bz2 是我们自己取的文件名,tar 并不会主动的产生创建的文件名喔!我们要自订啦! 所以扩展名就显的很重要了!如果不加 [-z|-j|-J] 的话,文件名最好取为 .tar 即可。如果是 -j 选项,代表有 bzip2 的支持,因此文件名最好就取为 .tar.bz2 ,因为 bzip2 会产生 .bz2 的扩展名之故! 至于如果是加上了 -z 的 gzip 的支持,那文件名最好取为 *.tar.gz喔!了解乎?

另外,由于“ -f filename ”是紧接在一起的,过去很多文章常会写成“-jcvf filename”,这样是对的, 但由于选项的顺序理论上是可以变换的,所以很多读者会误认为“-jvfc filename”也可以~事实上这样会导致产生的文件名变成 c ! 因为 -fc 嘛!所以啰,建议您在学习 tar 时,将“ -f filename ”与其他选项独立出来,会比较不容易发生问题。

闲话少说,让我们来测试几个常用的 tar 方法吧!

使用 tar 加入 -z, -j 或 -J 的参数备份 /etc/ 目录

有事没事备份一下 /etc 这个目录是件好事!备份 /etc 最简单的方法就是使用 tar 啰!让我们来玩玩先:

[dmtsai@study ~]$ su - # 因为备份 /etc 需要 root 的权限,否则会出现一堆错误

[root@study ~]# time tar -zpcv -f /root/etc.tar.gz /etc

tar: Removing leading `/' from member names &lt;==注意这个警告讯息

/etc/

....(中间省略)....

/etc/hostname

/etc/aliases.db

real 0m0.799s # 多了 time 会显示程序运行的时间!看 real 就好了!花去了 0.799s

user 0m0.767s

sys 0m0.046s

# 由于加上 -v 这个选项,因此正在作用中的文件名就会显示在屏幕上。

# 如果你可以翻到第一页,会发现出现上面的错误讯息!下面会讲解。

# 至于 -p 的选项,重点在于“保留原本文件的权限与属性”之意。

[root@study ~]# time tar -jpcv -f /root/etc.tar.bz2 /etc

....(前面省略)....

real 0m1.913s

user 0m1.881s

sys 0m0.038s

[root@study ~]# time tar -Jpcv -f /root/etc.tar.xz /etc

....(前面省略)....

real 0m9.023s

user 0m8.984s

sys 0m0.086s

# 显示的讯息会跟上面一模一样啰!不过时间会花比较多!使用了 -J 时,会花更多时间

[root@study ~]# ll /root/etc*

-rw-r--r--. 1 root root 6721809 Jul 1 00:16 /root/etc.tar.bz2

-rw-r--r--. 1 root root 7758826 Jul 1 00:14 /root/etc.tar.gz

-rw-r--r--. 1 root root 5511500 Jul 1 00:16 /root/etc.tar.xz

[root@study ~]# du -sm /etc

28 /etc # 实际目录约占有 28MB 的意思!

压缩比越好当然要花费的运算时间越多!我们从上面可以看到,虽然使用 gzip 的速度相当快,总时间花费不到 1 秒钟,但是压缩率最糟糕! 如果使用 xz 的话,虽然压缩比最佳!不过竟然花了 9 秒钟的时间耶!这还仅是备份 28MBytes 的 /etc 而已,如果备份的数据是很大容量的, 那你真的要考虑时间成本才行!

至于加上“ -p ”这个选项的原因是为了保存原本文件的权限与属性!我们曾在第六章的 cp 指令介绍时谈到权限与文件类型(例如链接文件)对复制的不同影响。 同样的,在备份重要的系统数据时,这些原本文件的权限需要做完整的备份比较好。此时 -p 这个选项就派的上用场了。 接下来让我们看看打包文件内有什么数据存在?

查阅 tar 文件的数据内容 (可察看文件名),与备份文件名有否根目录的意义

要察看由 tar 所创建的打包文件内部的文件名非常的简单!可以这样做:

[root@study ~]# tar -jtv -f /root/etc.tar.bz2

....(前面省略)....

-rw-r--r-- root/root 131 2015-05-25 17:48 etc/locale.conf

-rw-r--r-- root/root 19 2015-05-04 17:56 etc/hostname

-rw-r--r-- root/root 12288 2015-05-04 17:59 etc/aliases.db

如果加上 -v 这个选项时,详细的文件权限/属性都会被列出来!如果只是想要知道文件名而已, 那么就将 -v 拿掉即可。从上面的数据我们可以发现一件很有趣的事情,那就是每个文件名都没了根目录了!这也是上一个练习中出现的那个警告讯息“tar: Removing leading/' from member names(移除了文件名开头的 /' )”所告知的情况!

那为什么要拿掉根目录呢?主要是为了安全!我们使用 tar 备份的数据可能会需要解压缩回来使用, 在 tar 所记录的文件名 (就是我们刚刚使用 tar -jtvf 所察看到的文件名) 那就是解压缩后的实际文件名。 如果拿掉了根目录,假设你将备份数据在 /tmp 解开,那么解压缩的文件名就会变成“/tmp/<u>etc/xxx</u>”。 但“如果没有拿掉根目录,解压缩后的文件名就会是绝对路径, 亦即解压缩后的数据一定会被放置到 <u>/etc/xxx</u> 去!”如此一来,你的原本的/etc/ 下面的数据, 就会被备份数据所覆盖过去了!

Tips 你会说:“既然是备份数据,那么还原回来也没有什么问题吧?”想像一个状况,你备份的数据是两年前的旧版 CentOS 6.x, 你只是想要了解一下过去的备份内容究竟有哪些数据而已,结果一解开该文件,却发现你目前新版的 CentOS 7.x 下面的 /etc 被旧版的备份数据覆盖了!此时你该如何是好?大概除了哭哭你也不能做啥事吧?所以啰,当然是拿掉根目录比较安全一些的。

如果你确定你就是需要备份根目录到 tar 的文件中,那可以使用 -P (大写) 这个选项,请看下面的例子分析:

范例:将文件名中的(根)目录也备份下来,并察看一下备份文件的内容文件名

[root@study ~]# tar -jp&lt;u&gt;P&lt;/u&gt;cv -f /root/etc.and.root.tar.bz2 /etc

[root@study ~]# tar -jtf /root/etc.and.root.tar.bz2

/etc/locale.conf

/etc/hostname

/etc/aliases.db

# 这次查阅文件名不含 -v 选项,所以仅有文件名而已!没有详细属性/权限等参数。

有发现不同点了吧?如果加上 -P 选项,那么文件名内的根目录就会存在喔!不过,鸟哥个人建议,还是不要加上 -P 这个选项来备份! 毕竟很多时候,我们备份是为了要未来追踪问题用的,倒不一定需要还原回原本的系统中! 所以拿掉根目录后,备份数据的应用会比较有弹性!也比较安全呢!

将备份的数据解压缩,并考虑特定目录的解压缩动作 (-C 选项的应用)

那如果想要解打包呢?很简单的动作就是直接进行解打包嘛!

[root@study ~]# tar -jxv -f /root/etc.tar.bz2

[root@study ~]# ll

....(前面省略)....

drwxr-xr-x. 131 root root 8192 Jun 26 22:14 etc

....(后面省略)....

此时该打包文件会在“本目录下进行解压缩”的动作! 所以,你等一下就会在主文件夹下面发现一个名为 etc 的目录啰!所以啰,如果你想要将该文件在 /tmp 下面解开, 可以 cd /tmp后,再下达上述的指令即可。不过,这样好像很麻烦呢~有没有更简单的方法可以“指定欲解开的目录”呢? 有的,可以使用 -C 这个选项喔!举例来说:

[root@study ~]# tar -jxv -f /root/etc.tar.bz2 -C /tmp

[root@study ~]# ll /tmp

....(前面省略)....

drwxr-xr-x. 131 root root 8192 Jun 26 22:14 etc

....(后面省略)....

这样一来,你就能够将该文件在不同的目录解开啰!鸟哥个人是认为,这个 -C 的选项务必要记忆一下的! 好了,处理完毕后,请记得将这两个目录删除一下呢!

[root@study ~]# rm -rf /root/etc /tmp/etc

再次强调,这个“ rm -rf ”是很危险的指令!下达时请务必要确认一下后面接的文件名。我们要删除的是 /root/etc 与 /tmp/etc, 您可不要将 /etc/ 删除掉了!系统会死掉的~ ^_^

仅解开单一文件的方法

刚刚上头我们解压缩都是将整个打包文件的内容全部解开!想像一个情况,如果我只想要解开打包文件内的其中一个文件而已, 那该如何做呢?很简单的,你只要使用 -jtv 找到你要的文件名,然后将该文件名解开即可。 我们用下面的例子来说明一下:

# 1\. 先找到我们要的文件名,假设解开 shadow 文件好了:

[root@study ~]# tar -jtv -f /root/etc.tar.bz2 &#124; grep 'shadow'

---------- root/root 721 2015-06-17 00:20 etc/gshadow

---------- root/root 1183 2015-06-17 00:20 etc/shadow-

---------- root/root 1210 2015-06-17 00:20 etc/shadow &lt;==这是我们要的!

---------- root/root 707 2015-06-17 00:20 etc/gshadow-

# 先搜寻重要的文件名!其中那个 grep 是“撷取”关键字的功能!我们会在第三篇说明!

# 这里您先有个概念即可!那个管线 &#124; 配合 grep 可以撷取关键字的意思!

# 2\. 将该文件解开!语法与实际作法如下:

[root@study ~]# tar -jxv -f 打包档.tar.bz2 待解开文件名

[root@study ~]# tar -jxv -f /root/etc.tar.bz2 etc/shadow

etc/shadow

[root@study ~]# ll etc

total 4

----------. 1 root root 1210 Jun 17 00:20 shadow

# 很有趣!此时只会解开一个文件而已!不过,重点是那个文件名!你要找到正确的文件名。

# 在本例中,你不能写成 /etc/shadow !因为记录在 etc.tar.bz2 内的并没有 / 之故!

Tips 在这个练习之前,你可能要先将前面练习所产生的 /root/etc 删除才行!不然/root/etc/shadow 会重复存在,而其他的前面实验的文件也会存在, 那就看不出什么鬼~

打包某目录,但不含该目录下的某些文件之作法

假设我们想要打包 /etc/ /root 这几个重要的目录,但却不想要打包 /root/etc* 开头的文件,因为该文件都是刚刚我们才创建的备份文件嘛! 而且假设这个新的打包文件要放置成为/root/system.tar.bz2 ,当然这个文件自己不要打包自己 (因为这个文件放置在 /root 下面啊!),此时我们可以通过 --exclude 的帮忙! 那个 exclude 就是不包含的意思!所以你可以这样做:

[root@study ~]# tar -jcv -f /root/system.tar.bz2 --exclude=/root/etc* \

&gt; --exclude=/root/system.tar.bz2 /etc /root

上面的指令是一整列的~其实你可以打成:“tar -jcv -f /root/system.tar.bz2 --exclude=/root/etc* --exclude=/root/system.tar.bz2 /etc /root”,如果想要两行输入时,最后面加上反斜线 (\) 并立刻按下 [enter] , 就能够到第二行继续输入了。这个指令下达的方式我们会在第三章再仔细说明。 通过这个 --exclude="file" 的动作,我们可以将几个特殊的文件或目录移除在打包之列,让打包的动作变的更简便喔!^_^

仅备份比某个时刻还要新的文件

某些情况下你会想要备份新的文件而已,并不想要备份旧文件!此时 --newer-mtime 这个选项就粉重要啦! 其实有两个选项啦,一个是“ --newer ”另一个就是“ --newer-mtime ”,这两个选项有何不同呢? 我们在 第六章的 touch 介绍中谈到过三种不同的时间参数, 当使用 --newer 时,表示后续的日期包含“ mtime 与 ctime ”,而 --newer-mtime 则仅是 mtime 而已!这样知道了吧! ^_^ 。那就让我们来尝试处理一下啰!

# 1\. 先由 [find](../Text/index.html#find) 找出比 /etc/passwd 还要新的文件

[root@study ~]# find /etc -newer /etc/passwd

....(过程省略)....

# 此时会显示出比 /etc/passwd 这个文件的 mtime 还要新的文件名,

# 这个结果在每部主机都不相同!您先自行查阅自己的主机即可,不会跟鸟哥一样!

[root@study ~]# ll /etc/passwd

-rw-r--r--. 1 root root 2092 Jun 17 00:20 /etc/passwd

# 2\. 好了,那么使用 tar 来进行打包吧!日期为上面看到的 2015/06/17

[root@study ~]# tar -jcv -f /root/etc.newer.then.passwd.tar.bz2 \

&gt; --newer-mtime="2015/06/17" /etc/*

tar: Option --newer-mtime: Treating date `2015/06/17' as 2015-06-17 00:00:00

tar: Removing leading `/' from member names

/etc/abrt/

....(中间省略)....

/etc/alsa/

/etc/yum.repos.d/

....(中间省略)....

tar: /etc/yum.repos.d/CentOS-fasttrack.repo: file is unchanged; not dumped

# 最后行显示的是“没有被备份的”,亦即 not dumped 的意思!

# 3\. 显示出文件即可

[root@study ~]# tar -jtv -f /root/etc.newer.then.passwd.tar.bz2 &#124; grep -v '/$'

# 通过这个指令可以调用出 tar.bz2 内的结尾非 / 的文件名!就是我们要的啦!

现在你知道这个指令的好用了吧!甚至可以进行差异文件的记录与备份呢~ 这样子的备份就会显的更容易啰!你可以这样想像,如果我在一个月前才进行过一次完整的数据备份, 那么这个月想要备份时,当然可以仅备份上个月进行备份的那个时间点之后的更新的文件即可!为什么呢?因为原本的文件已经有备份了嘛!干嘛还要进行一次?只要备份新数据即可。这样可以降低备份的容量啊!

基本名称: tarfile, tarball ?

另外值得一提的是,tar 打包出来的文件有没有进行压缩所得到文件称呼不同喔! 如果仅是打包而已,就是“ tar -cv -f file.tar ”而已,这个文件我们称呼为 tarfile 。 如果还有进行压缩的支持,例如“ tar -jcv -f file.tar.bz2 ”时,我们就称呼为 tarball (tar 球?)!这只是一个基本的称谓而已,不过很多书籍与网络都会使用到这个 tarball 的名称!所以得要跟您介绍介绍。

此外,tar 除了可以将数据打包成为文件之外,还能够将文件打包到某些特别的设备去,举例来说, 磁带机 (tape) 就是一个常见的例子。磁带机由于是一次性读取/写入的设备,因此我们不能够使用类似 cp 等指令来复制的! 那如果想要将 /home, /root, /etc 备份到磁带机(/dev/st0) 时,就可以使用:“tar -cv -f /dev/st0 /home /root /etc”,很简单容易吧! 磁带机用在备份 (尤其是企业应用) 是很常见的工作喔!

特殊应用:利用管线命令与数据流

在 tar 的使用中,有一种方式最特殊,那就是通过标准输入输出的数据流重导向(standardinput/standard output), 以及管线命令 (pipe) 的方式,将待处理的文件一边打包一边解压缩到目标目录去。 关于数据流重导向与管线命令更详细的数据我们会在第十章 bash 再跟大家介绍, 下面先来看一个例子吧!

# 1\. 将 /etc 整个目录一边打包一边在 /tmp 解开

[root@study ~]# cd /tmp

[root@study tmp]# tar -cvf - /etc &#124; tar -xvf -

# 这个动作有点像是 cp -r /etc /tmp 啦~依旧是有其有用途的!

# 要注意的地方在于输出文件变成 - 而输入文件也变成 - ,又有一个 &#124; 存在~

# 这分别代表 standard output, standard input 与管线命令啦!

# 简单的想法中,你可以将 - 想成是在内存中的一个设备(缓冲区)。

# 更详细的数据流与管线命令,请翻到 [bash](../Text/index.html) 章节啰!

在上面的例子中,我们想要“将 /etc 下面的数据直接 copy 到目前所在的路径,也就是 /tmp 下面”,但是又觉得使用 cp -r 有点麻烦,那么就直接以这个打包的方式来打包,其中,指令里面的 - 就是表示那个被打包的文件啦! 由于我们不想要让中间文件存在,所以就以这一个方式来进行复制的行为啦!

例题:系统备份范例

系统上有非常多的重要目录需要进行备份,而且其实我们也不建议你将备份数据放置到 /root目录下! 假设目前你已经知道重要的目录有下面这几个:

/etc/ (配置文件)

/home/ (使用者的主文件夹)

/var/spool/mail/ (系统中,所有帐号的邮件信箱)

/var/spool/cron/ (所有帐号的工作排成配置文件)

/root (系统管理员的主文件夹)

然后我们也知道,由于第七章曾经做过的练习的关系, /home/loop* 不需要备份,而且 /root下面的压缩文件也不需要备份,另外假设你要将备份的数据放置到 /backups ,并且该目录仅有 root 有权限进入! 此外,每次备份的文件名都希望不相同,例如使用:backup-system-20150701.tar.bz2 之类的文件名来处理。 那你该如何处理这个备份数据呢?(请先动手作看看,再来察看一下下面的参考解答!)

# 1\. 先处理要放置备份数据的目录与权限:

[root@study ~]# mkdir /backups

[root@study ~]# chmod 700 /backups

[root@study ~]# ll -d /backups

drwx------. 2 root root 6 Jul 1 17:25 /backups

# 2\. 假设今天是 2015/07/01 ,则创建备份的方式如下:

[root@study ~]# tar -jcv -f /backups/backup-system-20150701.tar.bz2 \

&gt; --exclude=/root/*.bz2 --exclude=/root/*.gz --exclude=/home/loop* \

&gt; /etc /home /var/spool/mail /var/spool/cron /root

....(过程省略)....

[root@study ~]# ll -h /backups/

-rw-r--r--. 1 root root 21M Jul 1 17:26 backup-system-20150701.tar.bz2

解压缩后的 SELinux 课题

如果,鸟哥是说如果,如果因为某些缘故,所以你的系统必须要以备份的数据来回填到原本的系统中,那么得要特别注意复原后的系统的 SELinux 问题! 尤其是在系统文件上面!例如/etc 下面的文件群。SELinux 是比较特别的细部权限设置,相关的介绍我们会在 16 章好好的介绍一下。 在这里,你只要先知道,SELinux 的权限问题“可能会让你的系统无法存取某些配置文件内容,导致影响到系统的正常使用权”。

这两天 (2015/07) 接到一个网友的 email,他说他使用鸟哥介绍的方法通过 tar 去备份了/etc 的数据,然后尝试在另一部系统上面复原回来。 复原倒是没问题,但是复原完毕之后,无论如何就是无法正常的登陆系统!明明使用单人维护模式去操作系统时,看起来一切正常~但就是无法顺利登陆。 其实这个问题倒是很常见!大部分原因就是因为 /etc/shadow 这个密码文件的 SELinux 类型在还原时被更改了!导致系统的登陆程序无法顺利的存取它, 才造成无法登陆的窘境。

那如何处理呢?简单的处理方式有这几个:

通过各种可行的救援方式登陆系统,然后修改 /etc/selinux/config 文件,将 SELinux 改成permissive 模式,重新开机后系统就正常了;

在第一次复原系统后,不要立即重新开机!先使用 restorecon -Rv /etc 自动修复一下SELinux 的类型即可。

通过各种可行的方式登陆系统,创建 /.autorelabel 文件,重新开机后系统会自动修复SELinux 的类型,并且又会再次重新开机,之后就正常了!

鸟哥个人是比较偏好第 2 个方法,不过如果忘记了该步骤就重新开机呢?那鸟哥比较偏向使用第 3 个方案来处理,这样就能够解决复原后的 SELinux 问题啰! 至于更详细的 SELinux,我们得要讲完程序 (process) 之后,你才会有比较清楚的认知,因此还请慢慢学习,到第 16 章你就知道问题点了! ^_^

猜你喜欢

转载自blog.csdn.net/qq_22059611/article/details/84313326