第八章、文件与文件系统的压缩,打包与备份

《鸟哥的Linux私房菜-基础篇》第四版学习笔记目录

原书:《鸟哥的Linux私房菜-基础篇》第四版 | 作者: 鳥哥

8.1 压缩文件的用途与技术

8.2 Linux 系统常见的压缩指令

在Linux的环境中,压缩文件的扩展名大多是:“.tar, .tar.gz, .tgz, .gz, .Z, .bz2, *.xz”

常见的压缩文件扩展名

  • *.Z compress 程序压缩的文件(已过时);
  • *.zip zip 程序压缩的文件;
  • *.gz gzip 程序压缩的文件;
  • *.bz2 bzip2 程序压缩的文件;
  • *.xz xz 程序压缩的文件;
  • *.tar tar 程序打包的数据,并没有压缩过;
  • *.tar.gz tar 程序打包的文件,其中并且经过 gzip 的压缩
  • *.tar.bz2 tar 程序打包的文件,其中并且经过 bzip2 的压缩
  • *.tar.xz tar 程序打包的文件,其中并且经过 xz 的压缩

gzip、bzip2、xz仅能针对一个文件来压缩与解压缩,如此一来, 每 次压缩与解压缩都要一大堆文件,岂不烦人?此时,那个所谓的“打包软件, tar”就显的很重要啦!

8.2.1 gzip, zcat/zmore/zless/zgrep

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

1
2
3
4
5
6
7
8
9
gzip [-cdtv#] 文件名
zcat 文件名.gz

选项与参数:
 -c :将压缩的数据输出到屏幕上,可通过数据流重导向来处理;
 -d :解压缩的参数;
 -t :可以用来检验一个压缩文件的一致性~看看文件有无错误;
 -v :可以显示出原文件/压缩文件的压缩比等信息;
 -# :# 为数字的意思,代表压缩等级,-1 最快,但是压缩比最差、-9 最慢,但是压缩比最好!默认是 -6

当你使用 gzip 进行压缩时,在默认的状态下原本的文件会被压缩成为 .gz 的文件名,原始文件就不再存在了。 与 gzip 相反, gzip -d 会将原本的 .gz 删除,回复到原本的 services 文件。

1
2
# 范例四:将范例三解开的 services 用最佳的压缩比压缩,并保留原本的文件
gzip -9 -c services > services.gz

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

有备份数据使用的是 compress 创建出来的 .Z 文件,也无须担心,使用 znew 可以将该文件转成 gzip 的格示

8.2.2 bzip2, bzcat/bzmore/bzless/bzgrep

若说 gzip 是为了取代 compress 并提供更好的压缩比而成立的,那么 bzip2 则是为了取代 gzip 并提供更佳的压缩比而来的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
bzip2 [-cdkzv#] 文件名
bzcat 文件名.bz2

选项与参数:
 -c :将压缩的过程产生的数据输出到屏幕上!
 -d :解压缩的参数
 -k :保留原始文件,而不会删除原始的文件喔!
 -z :压缩的参数 (默认值,可以不加)
 -v :可以显示出原文件/压缩文件的压缩比等信息;
 -# :与 gzip 同样的,都是在计算压缩比的参数, -9 最佳, -1 最快!

8.2.3 xz, xzcat/xzmore/xzless/xzgrep

xz 的压缩比 bzip2 更高

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
xz [-dtlkc#] 文件名
xcat 文件名.xz

选项与参数:
 -d :就是解压缩啊!
 -t :测试压缩文件的完整性,看有没有错误
 -l :列出压缩文件的相关信息
 -k :保留原本的文件不删除~
 -c :同样的,就是将数据由屏幕上输出的意思!
 -# :同样的,也有较佳的压缩比的意思!

8.3 打包指令: tar

8.3.1 tar

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
tar [-z|-j|-J] [cv] [-f 待创建的新文件名] filename...  <===打包与压缩
tar [-z|-j|-J] [tv] [-f 既有的 tar文件名]             <===查看文件名
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 -jcv -f filename.tar.bz2 要被压缩的文件或目录名称
  • 查 询:tar -jtv -f filename.tar.bz2
  • 解压缩:tar -jxv -f filename.tar.bz2 -C 欲解压缩的目录

tar 并不会主动的产生创建的文件名喔!我们 要自订啦! 所以扩展名就显的很重要了! 如果不加 [-z|-j|-J] 的话,文件名最好取为 .tar 即可。

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

备份 /etc 最简单的方法就是使用 tar

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ su - # 因为备份 /etc 需要 root 的权限,否则会出现一堆错误

$ time tar -zpcv -f /root/etc.tar.gz /etc
# time 会显示程序运行的时间!看 real 就好了!
# 由于加上 -v 这个选项,因此正在作用中的文件名就会显示在屏幕上。
# 至于 -p 的选项,重点在于“保留原本文件的权限与属性”之意。

$ time tar -jpcv -f /root/etc.tar.bz2 /etc

$ time tar -Jpcv -f /root/etc.tar.xz /etc

$ ll /root/etc*

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

查阅 tar 文件的数据内容

1
tar -jtv -f /root/etc.tar.bz2

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

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

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

1
tar -jpPcv -f /root/etc.and.root.tar.bz2 /etc

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

将备份的数据解压缩

在当前目录解压缩

1
tar -jxv -f /root/etc.tar.bz2

在指定目录解压缩 -C 选项

1
tar -jxv -f /root/etc.tar.bz2 -C /tmp

仅解开单一文件的方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 1. 先找到我们要的文件名,假设解开 shadow 文件
$ tar -jtv -f /root/etc.tar.bz2 | grep 'shadow'

-rw-r----- root/shadow    1211 2021-03-16 14:28 etc/shadow
-rw-r----- root/shadow     701 2020-10-13 14:46 etc/gshadow-
-rw-r----- root/shadow     713 2020-12-02 11:05 etc/gshadow
-rw-r----- root/shadow    1211 2020-10-24 16:53 etc/shadow-

# 2. 将该文件解开!语法与实际作法如下:
# tar -jxv -f 压缩文件.tar.bz2 待解开文件名
# 在本例中,你不能写成 /etc/shadow !因为记录在 etc.tar.bz2 内的并没有 / 之故!
$ tar -jxv -f /root/etc.tar.bz2 etc/shadow

$ ll etc

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

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

1
2
3
4
5
6
7
tar -jcv -f /root/system.tar.bz2 \
--exclude=/root/etc* \
--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] , 就能够到第二行继续输入了

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

某些情况下你会想要备份新的文件而已,并不想要备份旧文件!此时 –newer-mtime 这个选 项就粉重要啦! 其实有两个选项啦,一个是“ –newer ”另一个就是“ –newer-mtime ”,这两个 选项有何不同呢? 我们在第六章的 touch 介绍中谈到过三种不同的时间参数

  • –newer 表示后续的日期包含“ mtime 与 ctime ”
  • –newer-mtime 则仅是 mtime

基本名称: tarfile, tarball ?

  • 如果仅是打 包而已,就是“ tar -cv -f file.tar ”而已,这个文件我们称呼为 tarfile
  • 如果还有进行压缩的支 持,例如“ tar -jcv -f file.tar.bz2 ”时,我们就称呼为 tarball

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

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

1
2
3
# 1. 将 /etc 整个目录一边打包一边在 /tmp 解开
cd /tmp
tar -cvf - /etc | tar -xvf -
  • 这个动作有点像是 cp -r /etc /tmp 啦~依旧是有其有用途的!
  • 要注意的地方在于输出文件变成 - 而输入文件也变成 - ,又有一个 | 存在~
  • 这分别代表 standard output, standard input 与管线命令啦!
  • 简单的想法中,你可以将 - 想成是在内存中的一个设备(缓冲区)。
  • 更详细的数据流与管线命令,请翻到 bash 章节啰!

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

系统备份范例

重要的目录有下面这几个:

  • /etc/ (配置文件)
  • /home/ (使用者的主文件夹)
  • /var/spool/mail/ (系统中,所有帐号的邮件信箱)
  • /var/spool/cron/ (所有帐号的工作排成配置文件)
  • /root (系统管理员的主文件夹)

假设你要将备份的数据放置到 /backups ,并且该目录仅 有 root 有权限进入! 此外,每次备份的文件名都希望不相同,例如使用:backup-system- 20150701.tar.bz2 之类的文件名来处理。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 1. 先处理要放置备份数据的目录与权限:
mkdir /backups
chmod 700 /backups
ll -d /backups

# 2. 假设今天是 2015/07/01 ,则创建备份的方式如下:
tar -jcv -f /backups/backup-system-20150701.tar.bz2 \
--exclude=/root/*.bz2 --exclude=/root/*.gz --exclude=/home/loop* \
/etc /home /var/spool/mail /var/spool/cron /root

ll -h /backups/

解压缩后的 SELinux 课题

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

简单的处理方式有这几个:

  • 通过各种可行的救援方式登陆系统,然后修改 /etc/selinux/config 文件,将 SELinux 改成 permissive 模式,重新开机后系统就正常了;
  • 在第一次复原系统后,不要立即重新开机!先使用 restorecon -Rv /etc 自动修复一下 SELinux 的类型即可。
  • 通过各种可行的方式登陆系统,创建 /.autorelabel 文件,重新开机后系统会自动修复 SELinux 的类型,并且又会再次重新开机,之后就正常了!

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

8.4 XFS 文件系统的备份与还原

8.5 光盘写入工具

8.6 其他常见的压缩与备份工具

8.6.1 dd

dd 不理会文件系统,单纯有啥纪录啥,因此不论该磁盘内的文件系统你是否认识,它都可以备份、还原的!

8.6.2 cpio

因为 cpio 可以备份任何东西,包括设备设备文件。不过 cpio 有个大问 题, 那就是 cpio 不会主动的去找文件来备份!啊!那怎办?所以啰,一般来说, cpio 得要配合类似 find 等可以找到文件名的指令来告知 cpio 该被备份的数据在哪里啊!

压缩算法比较

压缩比由低到高(压缩时间由快到慢):gzip < bzip2 < xz

参数压缩算法推荐文件后缀
-zgzip*.tar.gz
-jbzip2*.tar.bz2
-Jxz*.tar.xz
comments powered by Disqus