Linux操作系统(五):文件与文件系统的压缩

  • 压缩文件的用途与技术
  • 常见压缩命令
  • 打包命令
  • XFS文件系统的备份与还原
  • 光盘写入工具
  • 其他压缩备份工具

 一、关于本文内容的导读

这部分不涉及具体内容的解析,只是作为浏览和查找相关知识点的引导内容,采用【主题 | 命令 | 对应内容小节编号】三个关键信息的组合模式,依照这些信息可以快速查找到相关详细的示例和解析。

应用最广的压缩/解压缩/读取压缩文件/查询压缩文件数据的命令 | gzip | gunzip | zct | zgrep | 2.1.1
bzip2压缩程序的相关命令 | bzip2 | bunzip2 | bzcat | bzgrep | bzip2recover | 2.1.2
xz压缩程序的相关命令 | xz | xcat | xzgrep | 2.1.3
打包工具 | tar | 3.0
xfs文件系统备份 | xfsdump | 4.1
xfs文件系统还原 | xfsrestore | 4.2
查询磁盘容量使用情况(没有详细解析) | du | 4.2  #只是在这一节内容中应用过,之前的博客也没有详细的解析
对比两个文件的不同(没有详细解析) | diff | 4.2  #只是在这一节内容中应用过,之前的博客也没有详细的解析
创建镜像文件 | mkisofs | 5.1
远程或本地文件复制 | rsync | 5.2  #只是在这一节内容中应用过,之前博客中也没有详细的解析
光盘刻录工具 | wodim | cdrecord | 5.3
转换和拷贝文件 | dd | 6.1
存取归档 | cpio | 6.2

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

关于什么是文件压缩,简单的从字面意思来说就是将文件的大小减少,通常情况下我们一般采用字节作为计量单位Byte,但事实上计算机的最小计量单位bit,假设现在采用的字符编码格式是一个字符占用一个字节,如果现在要记录一个数字1,实际在八个比特上记录的就是这样:00000001。从这个最简单的案例中可以看到就是实际有效字符只使用了一个比特(即最后面那一个比特表示的1),这时候就可以通过压缩技术将那些实际无效的比特丢掉,从而就实现了文件空间变小的目的,这就是文件压缩技术。

除了这种直接丢掉无效字符的方式还有将重复数据进行统计,比如有这样的数据【11111...】共100个1时,那么压缩技术会记录100个1,而不是真实的用一百个字节来记录这一串数据,这同样是实现文件压缩的一种技术思路,除了上面提到的这两种思路以外还有很多技术和算法被创造出来用来实现文件压缩的目的。

当然文件被压缩过后就不能被正常的读取使用,还需要有将其还原的技术,将压缩文件还原的就叫做解压缩。相关的技术文档可以参考:http://www.ietf.org/rfc/rfc1952.txt

2.1压缩文件与扩展名

在Linux的环境中扩展名是没有什么作用的,但是由于压缩技术的发展,不同的压缩技术使用的彼此之间无法互通压缩/解压缩文件,当拿到一个压缩文件时我们就必须要选择一种与其压缩技术相匹配的解压缩程序来获取源文件,所以为了方便对照,在压缩文件后面拓展了扩展名,Linux常见的压缩文件扩展名有:tar、tar.gz、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的压缩

由于压缩文件只能针对单个文件进行,如果一次压缩和解压很多个文件就会现得很麻烦,这时候打包程序就可以大展身手了。tar是可以将很多文件打包成一个文件,甚至目录也可以被打包,不过单纯的tar功能只是打包。后GNU计划中,将整个tar与压缩的功能结合起来,由此就产生了便捷的打包压缩功能,下面就来逐个的了解这些压缩程序对应的命令及其应用:

2.1.1gzip,zcat/zmore/zless/zgrep

借用gzip这个应用最广的压缩命令来简单的介绍一下围绕压缩文件的操作,前面说过压缩文件是为了减少文件的大小,降低存储设备的容量消耗,但压缩文件只能用于存储和传输,但需要使用文件时我们依然需要将压缩文件转换成原始文件数据。

所以,但文件压缩以后想要使用文件时,就需要将文件在转换回原始文件,那么这就有两种场景,一种是只是当前使用文件数据,那么就直接将压缩文件里的原始文件数据解压输出即可;还有一种可能需要长期的使用原始文件,这时候就需要将压缩文件还原成一个完整的原始文件存储下来;还有一种需求可能是你只想查看文件中是否又包含某个数据,同样也有相关的命令可以实现查找压缩文件中的数据,而不需要将文件解压。

围绕以上的分析在来通过man查看gzip的文档:

 gzip [ -acdfhlLnNrtvV# ] [-S 后缀] [ 文件名 ...  ]
 gunzip [ -acfhlLnNrtvV ] [-S 后缀] [ 文件名 ...  ]
 zcat [ -fhLV ] [ 文件名 ...  ]

首先来看这三个命令,gzip负责压缩文件、gunzip负责解压文件、zcat输出被压缩文件数据;然后还有一个grep命令可以用来查找压缩文件中的数据,这个命令不属于压缩文件命令,它仅仅是用来查询文件中的数据,这个查询并不需要解压压缩文件。下面就先来解析了一些gzip相关的选项,然后使用/etc/services这个文件来测试作为示例:

-c:将压缩的数据输出到屏幕上,可以通过数据重定向来处理;
-d:解压缩的选项,同等与gunzip这个命令;
-t:可以用来检验压缩文件的一致性,检查文件是否有误;
-v:可以显示出原文件/压缩文件的压缩比等信息;
-#:#表示数字的意思,用来表示压缩等级(1~9级),级别越高压缩比越大,压缩速度越慢,默认是6;

关于其他的选项,在示例后面再逐个解析,这里先来看示例代码:

 cd /tmp  #进入到tmp目录下测试文件压缩相关操作,tmp是一个用作临时文件目录,这方面相关内容在Linux操作系统(附二)博客中有介绍

 ls -ldSr /etc/*  #查询etc下的文件信息列表,并以小到大排列

 cp /etc/services .  #将services拷贝到tmp目录下作为测试文件

 gzip -v services  #使用gzip压缩文件,并打印压缩比信息:services:     79.7% -- replaced with services.gz

 ll services  #查看原文件:无法访问services: 没有那个文件或目录

 ll services.gz  #查看压缩文件:-rw-r--r--. 1 tx tx 136088 6月  19 08:05 services.gz

 ll /etc/services  #查看etc下的services,因为tmp下的原文件被压缩后就无法查看了,要对比压缩前后的文件信息就只能去etc下找到原始文件,文件信息如下:

 ## -rw-r--r--. 1 root root 670293 6月   7 2013 /etc/services ##可以看到压缩文件的容量相对源文件减少了670293-136088=534205,压缩文件的大小只有源文件的约20%

上面的示例展示了gzip压缩文件的基本操作以及一些基本信息的介绍,有一个需要注意就是文件压缩后原文件就不存在了。

gzip压缩文件会以gz作为后缀添加在当前目录下,回到语法中的-S选项,这个选项可以自定义压缩文件的任意后缀名,没错是任意后缀名,但需要注意的是应该尽量避免使用gz、z以外的其他后缀名,如果后缀名被设置为空将会导致以后使用gunzip解压时会对任意文件都执行解压过程,例如 gunzip -S "" * ,其实在一开始gzip采用的默认后缀是z,后来为了避免pack(1)冲突就改成了gz,所以实际上gunzip能解压gz、zip、z后缀的gzip、zip、compress压缩文件。

实际上gzip是GNU计划开发出来的压缩程序,并且兼容替代了compress压缩程序,后来GNU又开发出了bzip2及xz压缩比更好的压缩程序,所以gzip可以解开gzip、zip、compress等软件所有压缩的文件,在后面都会涉及介绍相关内容,这里就接着先来看gzip读取压缩文件、解压缩gz压缩文件:

 zcat services.gz  #读取gz压缩文件,由于services.gz的原文件services是文本文件,所以就是用zcat/zmore/zless去读取,这时候你会发现在终端上会打印出很多文件数据

 gzip -d services.gz  #解压gz压缩文件,在语法中不是gunzip解压gz压缩文件吗?还记得在前面的博客中提到的ll命令重命名吗?所以gzip -d与gunzip是等价的

关于读取gz压缩文件,这里写需要注意的内容,读取文本文件使用的是cat/more/less,即cat命令,与之相对应读取文本文件压缩的压缩文件就是使用zcat/zmore/zless,即zcat命令,如果不是文本文件就不能使用cat来读取,对应的非文本文件压缩的压缩文件也就不能使用zcat来读取。然后zcat读取出来的文件数据是文本文件的原始数据,实际上zcat/zmore/zless内部先将gz压缩文件解压然后再输出。

关于gz解压缩的-d选项与gunzip在示例注释中已经说的很清楚了,这里就不赘述了,然后说明一下解压缩会在当前目录下生成一个没有后缀名的原文件,压缩文件就不会再存在了,这与压缩文件是生成压缩文件删除原文件的内在逻辑是一样的。

最后来关注一下gzip的压缩比和gzip压缩文件的查询,还是一样先来看示例:

 gzip -9 -c services > services.gz  #这里-9就是指定的压缩等级来实现压缩,关于-c这个选项在下面的详细解析内容中介绍

 zgrep -n 'http' services.gz  #这里实际上是使用egrep来打印指定数据(即查询)所在行的整行数据,zgrep就是实现egrep在压缩文件中收索文件数据,匹配的方式是正则

这里需要注意-c选项的意思是将文件压缩后使用标准输出打印在终端上,然后使用“>” 将输出的数据保存到services.gz这个名称的文件内,使用">"来用文件收集数据就不会打印到屏幕上了,并且这时候是新建一个文件即示例中的services.gz,而不会删除services这个原文件。所以这行命令写成 gzip -9 -v services 与之前默认的压缩比压缩就没什么区别了,它会删除原文件services然后生成一个services.gz压缩文件。

关于-9这个选项参数实现的压缩比没有什么太多要解释的,在前面的选项解释中对应的就是-#已经有说明了,数字越大压缩的比例就越大,生成的压缩文件就越小。

然后关于前面提到的几个重要的选项中就是-t没有演示,这个选项使用很简单,比如这样 gzip -tv services.gz 它就会去检查压缩文件是否有错,如果没有错就会打印出“OK”。以上就是使用gzip解析的关于文件压缩的操作的主要内容,接下来再简单的介绍一些必要gzip命令的一些其他选项:

-a:Ascii文本模式:按本地习惯转换行结束符。该选项仅在一些非Unix系统上有效。对于MSDOS,在压缩时CR LF(译注:即回车和换行符)被转换为LF,在解压时LF被 转换为CR LF。
-f:强制压缩和解压,对于一些无法识别的格式强制执行相关操作。
-l:列出每个压缩文件的相关信息;
-L:显示gzip的许可证信息;
-n:在压缩时不保留原文件的文件名和时间信息;
-N:在压缩时总是保留原文件名和时间信息,在解压时如果存在原文件名和时间信息则恢复;
-r:递归范文目录结构,如果压缩文件中存在目录,会压缩目录下所有文件;
#最后就是-S选项在之前的详细内容解析中已经有非常详细的介绍了,这里就不再赘述,如果还不了解可以查看博客的详细内容。

有了对gzip的详细了解,接下来的bzip2和xz压缩命令就简单的介绍一下使用,如果有非常大的差异情况下的话会做一些解析;

2.1.2bzip2,bzcat/bamore/bzless/bzgrep

 bzip2 [ -cdfkqstvzVL# ] [ filenames ...  ]
 bunzip2 [ -fkvsVL ] [ filenames ...  ]
 bzcat [ -s ] [ filenames ...  ]
 bzip2recover filename

通过man文档bzip2可以看到对它的定义:一种块排序文件压缩软件。这里暂时不要太多的去关注什么是快排序文件,它所说的其实就是一种数据结构,这是它实现文件压缩算法的基础,对于应用层来说我们并不需要关注它,当然有一天如果你想实现自己的一套压缩程序的时候可以研究一下这方面的东西。

那为什么有了gzip还会要使用bzip2呢?归根到底还是为了获得更好的压缩效果,相对gzip的压缩比来说bzip2的压缩比更高。

bzip2的选项几乎与gzip一模一样,这从语法中就可以看出来,只是相对gzip多了一个bzip2recover,它是用来恢复损坏的bzip2文件用的。关于bzip2的解析这里就只简单的介绍它的主要选项即操作演示,更多的内容可以参考man的文档:

-c:将数据压缩或解压后使用标准输出打印在终端上;
-d:强制解压缩;
-k:保留原文件,而不会删除原始文件;
-z:强制压缩(默认值,可以不加);
-v:可以显示出原文件/压缩文件的压缩比等信息;
-#:与gzip同样的,都是计算压缩比的参数,-9最佳,-1最快;

下面是bzip2的示例代码,根据注释和对比gzip的示例理解:

 bzip2 -v services  #压缩services,生成压缩文件services.bz2并删除services原文件。如果使用-k选项就不会删除原文件,与使用-c > services.bz2实现效果一样

 bzcat services.bz2  #读取压缩文件,输出的是services原文件数据,与bzcat/bzmore/bzless相对应得cat/more/less一样,因为services是文本文件

 bzcat services.bz2 | grep 'http'  #按照查询读取压缩文件数据,类似跟zgrep的功能一样

 bzgrep 'http' services.bz2  #跟上一条命令的效果一样,也是按照查询读取压缩文件数据

 bzip2 -d services.bz2  #解压缩services.bz2

 bzip2 -v9 services  #以9作为压缩级别压缩services

 bzip2recover services.bz2  #恢复顺坏得bz2文件

 

2.1.3xz,xzcat/xzmore/xzless/xzgrep

 xz [-dtlkc#] 文件名

 xcat 文件名xz

xz与bzip2一样,它的出现都是为了实现更大得压缩比,将文件压缩的更小一些,只是bzip2对压缩比的提升依然还不能被满足,所以xz也就由此诞生,它可以实现相比bzip更高的压缩比。当然所以压缩都是用时间换空间,所以xz实现更大的压缩比付出的代价也就是要使用更多的时间,这也就意味着它对CPU的消耗更大,所以在实际应用中服务上使用的还是gzip比较多,xz更多被应用在应用程序中,而bzip2的应用相对就少一些。

-d:解压缩;
-t:测试压缩文件的完整性,看看有没有错误;
-l:列出压缩文件的相关信息;
-k:保留原文件;
-c:将压缩文件数据标准输出打印到终端上;
-#:1-9级压缩

有了前面gzip和bzip2的详细解析,xz应该就没有必要在说什么的必要了,如果下面的示例不理解可以参考上面gzip和bzip2的解析内容或者man文档。

 xz -v services  #压缩文件

 xz -l services.xz  #列出压缩文件信息,这里会列出压缩前后的容量数据,还有编码方式

 xzcat services.xz  #读取压缩文件,输出services的源文件数据

 xzgrep 'http' services.xz  #按照查询读取压缩文件数据

 xz -d services.xz  #解压

 xz -k services  #保留原文件压缩文件

 ll services services.xz  #查看原文件和压缩文件

 rm services.xz  #删除压缩文件

 xz -9v services  #使用最大压缩级别压缩文件

 xz -l services.xz  #查看压缩文件的信息

 三、打包与压缩

在前面介绍了gzip、bzip2、xz的压缩命令的使用,日常我们使用windows系统都知道,在windows上的winRAR这类压缩软件可以将多个数据包装成一个文件的样式,当然在Linux中也有打包功能的应用,这个打包应用就是tar,但是它本身不提供压缩功能,而是集成支持gzip、bzip2、zx来同时实现压缩打包功能。

关于tar的语法当你使用man查看它的文档时绝对会有一种窒息的感觉,所以这里我参考的是一本教程书上的命令语法,通过这种间接的语法学习以后再去理解man文档中的tar语法就会容易很多,所以先来看命令语法:

 tar [-Z | -z | -j | -J] [cv] [-f 待建立的新文件] filename...   #打包与压缩

 tar [-Z | -z | -j | -J] [tv] [-f 既有的tar文件名]  #查看文件名

 tar [-Z | -z | -j | -J] [xv] [-f 既有的tar文件名] [-C 目录]  #解压缩

tar命令的选项及参数解析:

-c:建立打包文件;
-t:查看打包文件的内容含有那些文件名(查看文件名)
-x:解包或解压缩的功能,可以搭配-C在特定目录解压
-Z:通过compress的支持进行压缩/解压缩
-z:通过gzip的支持进行压缩/解压缩
-j:通过bzip2的支持进行压缩/解压缩
-J:通过xz的支持进行压缩/解压缩
-v:在压缩/解压缩过程中将正在处理的文件名显示出来
-f:用于生成新文件设置文件名
-C:将文件解压缩保存到指定的目录下
-p:保留备份数据的原本权限与属性(p是小写)
-P:保留绝对路径,意思就是允许备份数据中包含有根目录存在的意思(P是大写)
-exclude=FILE:在压缩过程中,不要将FILE打包

通过上面这三个简化的命令语法就可以了解到tar实现压缩的集成方式是通过Z、z、j、J四个选项来实现的,不过现在一般都不会使用compress了,所以Z选项一般不会使用了。然后就是在于发中将-f独立出来了,这是因为在语法中选项是可以不按顺序的,比如正常这样写-jcvf不会有问题,但如过是-jvfc这样写最后文件名就变成了c。除了这一个小小的注意事项以外就没什么太多的东西需要说的了,然后需要注意的是打包需要管理权限,所以需要切换到root用户才能测试下面的示例,现在来看示例:

 su -  #切换管理员身份

 cd /tmp  #进入到tmp目录下测试

 tar -zpcv -f etc.tar.gz /etc  #这可能需要等一些时间才能完全打包完成,需要注意的就是命名

 tar -ztv -f etc.tar.gz  #查看打包备份的文件,注意虽然gzip能解压compress的压缩文件,但在tar打包内的压缩文件不能使用gzip解压,所以选项不能使用-j,还需要用-z

 rm etc.tar.gz  #删除这个打包文件,方便测试下一个,不过需要注意的是前面查看文件你会发现文件没有根目录,而是直接从etc开始的

 tar -jpPcv -f etc.tar.gz /etc  #打包压缩文件,并且保留根目录

 tar -jtv -f etc.tar.gz   #再来查看打包备份的文件,看文件的路径和名称你会发现这一回文件的目录保留根目录

 tar -jxv -f etc.tar.gz  #解压打包压缩文件,这时候你就可以看到在tmp目录下多了一个etc子目录

 ls -dl etc  #查看etc目录

 ll etc  #然后查看文件你会发现原etc下的文件都在这儿了

 ll etc.tar.gz  #这里你会发现原来压缩文件并没有删除

 mkdir ./tar  #在tmp目录下创建一个tar来接收解压文件

 tar -jxv -f etc.tar.gz -C ./tar  #将文件解压到指定的目录下,同样会在这个指定的目录下生成一个etc子目录

关于tar的打包压缩、查看打包压缩文件中包含的文件、解压打包压缩文件这些在上面的示例中都演示的很详细了,对照注释和前面的选项解析很容易理解,以上的内容主要是以gzip压缩程序实现的,如果想用其他压缩程序可以参考选项中关于其他压缩程序的选项应用,接下来了解一下仅从压缩包中解压一个文件如何实现:

3.1解压打包压缩文件中的一个文件

 tar [-Z | -z | -j | -J ] xv -f 打包压缩文件 指定解压的文件名

关于解压打包文件中的某一个文件需要注意的就是要解压的文件名是打包时保留的全路径名,比如前面示例中没有保留根目录的某个文件就是etc/xxx,如果使用-P保留了根目录就是/etc/xxx,下面来看示例:

 tar -jtv -f etc.tar.gz | grep 'shadow'  #通过grep筛选包含shadow字符串的文件名,这里应该会获得几个文件的信息,然后选择shadow文件作为解压示例

 tar -jxv -f etc.tar.gz /etc/shadow  #通过上一步查询可知我之前的压缩保留根目录,然后解压后文件由于没有指定路径会存到当前目录下,同样回生成一个etc目录

 ll etc  #查询刚刚解压的文件信息,如果不出文件就可以在当前目录下查看到etc目录下有一个文件shadow

3.2压缩打包某个目录,但不包含目录下的某些文件

 tar [-Z | -z | -j | -J] [-cv] -f 待建立的新文件 --exclude=不打包的文件1(全路径) \

 --exclude=不打包的文件2(全路径) 打包目录1 打包目录2...

关于不包含某个文件的实现选项就是--exclude,然后这里有一个(\)反斜杠可能对不熟悉linux终端上的语法无法理解,这个反斜杠的作用就是用来转义【enter】回车键的,它会让回车键不立即执行命令,而是转到下一个行继续输入,这样就可以将两行命令拼接成一行命令来使用。

语法解释清楚了,就来做一个示例,这里我还是打包/etc这个目录,只是不打包这个目录下的shadow和shoadow-这两个文件,下面来看整个示例的操作过程:

 ll /etc/shadow*  #查看确认一下etc下不打包的文件

 tar -jcv -f etc.tar.gz --exclude=/etc/shadow \

 --exclude=/etc/shadow- /etc  #由于不想把语法写的很复杂,--exclude可不止像语法和示例中一样不打包两个,而是可以接n个,打包目录也可以是n个

 ll etc.tar.gz  #查看一下刚刚打包压缩生成的文件

 -jtv -f etc.tar.gz | grep 'shadow'  #然后我们来查看一下是是不是没有将指定的文件打包进来,下面的打印结果确时证明了没有打包指定的文件
---------- root/root      1007 2022-06-13 00:54 etc/gshadow
-rw-r--r-- root/root       214 2020-10-16 03:24 etc/pam.d/sssd-shadowutils
---------- root/root      1005 2022-06-13 00:54 etc/gshadow-

3.3备份比某个时间还要新的文件

备份文件是压缩打包的常用应用之一,特别是按照时间段来备份文件,打包比某个时间还早的文件涉及的选项在前面介绍中没有出现,这个选项是--newer-mtime,下面是语法:

 tar [-Z | -z | -j | -J] -[cv] -f 待建立的新文件名 --newer-mtime=[date] /要打包的目录/*

关于备份比某个时间还要新的文件这个示例依然使用/etc目录下的文件,下面直接来看示例操作:

 ll /etc/passwd  #由于每个人的系统文件时间都存在差异,先来查看一下etc下的一个文件信息,用这个文件的时间作为参考,不然可能因为时间设置不对打包不到文件

 tar -jcv -f etc.tar.gz --newer-mtime='2022/6/13' /etc/*  #如果打包成功的话有下面这样的打印结果

 ...

 /etc/systemd/system/default.target          #这里是符合条件的打包文件
 tar: /etc/systemd/system.conf: 文件未改变;未输出    #这里是不符合条件的文件没有打包的提示信息
 ...

3.4tar的管道命令和数据流特性实现数据拷贝、基本名称(重点)

关于文件拷贝我们第一个想到的肯定是cp这个拷贝命令,但是如果要拷贝一个目录下所有文件就会显得有些麻烦,就算使用-r递归拷贝也只能实现一个子目录分支的文件拷贝,这时候使用tar就可以很方便的解决这种需求,这是因为tar的底层实现方式是基于标准输入输出的数据流重定向(standard input/standard output),以及管道命令(pipe)的方式,将待处理的文件一边打包一边解压到目标目录,关于Linux系统上的数据流重定向与管道命令在后面的bash会有详细介绍,我在之前的nodejs相关博客中有一篇关于流的文章: nodejs的tream(流)解析与模拟文件读写流源码实现,这篇博客所解析的内容核心原理与Linux的数据流重定向和管道命令是一样的,如果有javaScript或nodejs经验的可以参考。

如果只是为了实现文件拷贝就没有必要调用压缩文件程序,这在tar一开始就说过它本身是一个打包应用,压缩文件只是调用了压缩程序的接口,而如果不调用压缩程序的打包生成的文件叫做tarfile,反之调用了压缩程序的打包生成的文件叫做tarball,这也被称为tar打包生成文件的基本名称。

下面来看关于tar实现文件拷贝的示例操作:

 tar -cvf - /etc | tar -xvf -  #这里的“-”表示一个被打包的文件,同样会在当前目录下生成一个etc目录,并会把原/etc下的所有文件拷贝到这个文件夹下

关于tar的拷贝除了可以解决这种目录结构比较复杂的大量文件拷贝问题,还有一个重要的应用就是将文件打包到某些设备中,比如磁带是一次性读/写设备,所以磁带备份文件肯定不能使用cp这个命令来拷贝,所以磁带备份使用tar实现是最合理的方式。

3.5解压缩后的SELinux问题

先来了解一下系统备份的基本操作,系统上有很多重要的目录需要备份,最基本的应该包含以下这些目录:

/etc/(配置文件)
/home/(用户家目录)
/var/spool/mail/(系统中所有账号的邮箱)
/var/spool/cron/(所有账号的定时任务配置文件)
/root/(系统管理员的家目录)

当然在这里目录下也不是所有文件都需要备份,比如有/hom/loop*、/root下面的压缩文件,现在如果要将以上的目录备份到/backups,并且希望每次打包的名称都不一样,名称格式是这样“backup-system-20220620.tar.gz”,实现命令是:

 mkdir /backups  #创建一个用于保存被文件的目录

 tar -jcv -f /backups/backup-system-20220620.tar.gz \

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

 /etc /home /var/spool/mail /var/spool/cron /root  #这是实现备份的全部代码

 ll -h /backups/  #查看备份文件目录下压缩打包的备份文件信息:-rw-r--r--. 1 root root 12M 6月  20 19:50 backup-system-20220620.tar.gz

关于系统备份后面会有更详细的内容,这里只是为了演示打包命令tar的应用,然后就是要解释另一个问题,也是这一小节的主题SELinux问题,SELinux是比较特别的详细权限设置,SELinux的权限问题可能会导致系统无法读写某些配置文件内容,导致影响系统的正常使用,那这些问题跟打包和备份有什么关系呢?

比如当你还原系统备份文件时,其中会有一个文件/etc/shadow,这个密码文件的SELinux类型在还原时被更改了,导致系统的登入程序无法顺利读取它,就会导致无法登入的情况,解决它的方案有以下几种:

1.通过各种可行的恢复方式登入系统,然后修改/etc/selinux/config文件,将SELinux改成permissive模式,重新启动系统就会正常了;

2.第一次恢复系统后不要立即重启,先使用restorecon -Rv /etc自动修复一下SELinux的类型即可;

3.通过各种可行的方式登入系统,建立/.autorelabel文件,重新启动后系统会自动修复SELinux的类型,并且又会在再次重启后恢复正常。

 四、XFS文件系统的备份与还原

前面讲的tar实现的文件备份是基于目录树系统进行备份的,还记得上一篇博客讲的文件系统吗?基于目录所备份的大部分都是日常用户工作的文件和管理系统相关的文件,有时候我们会将一些归类特点特别明显的数据会放到一个文件系统下来管理,所以这时候备份文件系统或许是更优的方案,关于xfs文件系统的备份相关命令是xfsdump、xfsrestore,其中xfsdump负责备份、xfsrestore负责还原,下面先来了解xfs文件系统的备份:

4.1xfs文件系统备份

xfsdump的文件功能相对tar来说更强大,它除了可以实现完整备份之外,还可以实现增量备份。所谓增量备份就是在一次完整备份之后,第二次备份只需要将发生改变的文件增加到备份中,而不再对整个文件系统进行备份。然就是要注意xfsdump的一些限制:

1.不支持没有挂载的文件系统备份;
2.必须使用root的权限才能操作,这与tar打包是一样的;
3.只能备份xfs文件系统;
4.备份下来的数据(文件或存储媒介)只能让xfsrestore解析;
5.因为xfsdump是通过文件系统的UUID来辨别个备份文件,因此不能备份两份两个相同的UUID的文件系统;

关于xfsdump命令的语法在man文档中也是比较复杂的,这里依然采用简化的语法展示,如果需要了解详细语法参考man文档:

 xfsdump [-L S label] [-M M label] [-l #] [-f 备份文件名] 待备份数据

 xfsdump -I

常用xfsdump命令选项解析:

-L:记录每次备份的session标头,这里可以填写针对次文件系统的简易说明;
-M:记录存储媒介的标头,这里可以填写此媒介的简易说明;
-l:指定等级,有0~9共十个级别,默认为0,即完整备份;
-f:这个跟tar差不多,就是备份的文件名,但不同的是可以是设备文件名或其他一般文件名;
-I:从/var/lib/xfsdump/inventory列出目前备份的信息状态;

下面进入正式的示例演示,如果/boot划分出了独立的文件系统就用这个作为测试,如果没有可以参考上一篇博客 Linux操作系统(四):磁盘与文件系统管理创建一个文件系统来测试或者找一个当前系统的文件系统测试(千万别用根目录挂载的文件系统测试,数据量太大了):

 df -h /boot  #测试/boot是否是挂载了一个独立文件系统,判断是否是一个文件系统就看目录所属的文件系统挂载点是否是在当前目录上挂载

 #文件系统        容量  已用  可用 已用% 挂载点
 #/dev/sda1      1014M  173M  842M   18% /boot  #所属文件系统是/dev/sda1,挂载点/boot,所以我当前测试的系统上/boot是一个独立的文件系统

 xfsdump -l 0 -L boot_all -M boot_all -f /srv/boot.dump /boot  #-L -M可以不加,但备份时就会进入交互模式,需要手动回车

下面这是我刚刚测试备份/boot的输出信息,可以的看看它的内容,有利于了解xfsdump的备份机制:

xfsdump: using file dump (drive_simple) strategy
xfsdump: version 3.1.7 (dump format 3.0) - type ^C for status and control
xfsdump: level 0 dump of localhost.localdomain:/boot       #开始备份本机/boot
xfsdump: dump date: Tue Jun 21 00:38:51 2022            #备份的时间
xfsdump: session id: 08f2814d-d350-410a-9146-0215d21cf7d4    #这次备份的dump的ID
xfsdump: session label: "boot_all"                  #备份的标签(名称)
xfsdump: ino map phase 1: constructing initial dump list     #开始备份程序
xfsdump: ino map phase 2: skipping (no pruning necessary)
xfsdump: ino map phase 3: skipping (only one dump stream)
xfsdump: ino map construction complete
xfsdump: estimated dump size: 147377536 bytes
xfsdump: /var/lib/xfsdump/inventory created
xfsdump: creating dump session media file 0 (media 0, file 0)
xfsdump: dumping ino map
xfsdump: dumping directories
xfsdump: dumping non-directory files
xfsdump: ending media file
xfsdump: media file size 147002368 bytes
xfsdump: dump size (non-dir files) : 146732288 bytes
xfsdump: dump complete: 5 seconds elapsed
xfsdump: Dump Summary:
xfsdump:   stream 0 /srv/boot.dump OK (success)
xfsdump: Dump Status: SUCCESS

然后再来看看备份生成的文件信息即相关的文件信息:

 ll /srv/boot.dump  #查看生成的备份文件信息:-rw-r--r--. 1 root root 147002368 6月  21 00:38 /srv/boot.dump

 ll /var/lib/xfsdump/inventory  #除了生成备份文件以外,还会将备份的相关信息(文件系统、时间、session ID等)写入到这里,作为下一次增量备份的参考依据

再继续使用xfsdump进行增量备份:

 xfsdump -I  #在做增量备份之前使用-I(大写i)来查看备份的信息状态

 dd if=/dev/zero of=/boot/testing.img bs=1M count=10  #在备份前现在/boot下新建一个10MB的文件,方便实现差异化备份

 xfsdump -l 1 -L boot_2 -M boot_2 -f /srv/boot.dump1 /boot  #做增量备份,注意这里改动的选项参数

 ll /srv/boot*  #查看备份文件

 xfsdump -I  #查看备份的信息状态,你会发现这时候在信息中打印出了两个session的信息

文件系统的常规备份操作其实很简单,这里再接着来看如何还原xfsrestore。

4.2xfs文件系统还原

在前面的xfs文件系统备份中就提到过了,xfs文件系统备份与还原一整套机制,备份使用的是xfsdump命令,还原使用的是xfsrestore命令,下面先直接来看它的语法,当然这里的语法依然是简化版,如果要了解它的完整语法还是参考man文档:

 xfsrestore -I  #查看备份文件,与xfsdump -I的作用是一样的(I是大写i)

 xfsrestore [-f 备份文件] [-L S_label] [-s] 待恢复目录  #单一文件全系统恢复

 xfsrestore [-f 备份文件] -r 待恢复目录  #通过增量备份文件来恢复

 xfsrestore [-f 备份文件] -i 待恢复目录  #进入交互模式()

再来看xfsrestore的主要选项详细内容和参数解析:

-I:查询备份数据信息,这些信息被保存在/var/lib/xfsdump/inventory中,与xfsdump -i所查看的内容一致;
-f:用来指定要还原的备份源,即备份文件名。也可能是备份设备名,比如磁带设备的路径名;
-L:用来指定还原文件的备份标签,即S_label,可以通过-I查找到S_label;
-s:用来指定要还原的文件原目录,被指定的目录下所有文件和子目录下的文件都会被还原;
-r:用来选择操作模式,简单的说如果是用文件备份数据就不需要使用这个选项即默认模式,如果是一个磁带内有多个文件则需要这个选项来完成累积恢复;
-i:进入交互模式,一旦开始读取备份文件上的目录层次结构就进入交互模式,使用子命令来查看目录和文件层次结构,选择要提取的文件和目录,相关子命令参考man文档;
【待恢复的目录】:可以是备份文件对应的文件系统挂载目录及文件目录,也可以指定一个全新的目录来保存还原文件;

下面来看关于xfsrestore的文件系统还原示例:

 xfsrestore -I  #查看当前xfs文件系统的备份信息;

 xfsrestore -f /srv/boot.dump -L boot_all /boot   #这个还原会直接覆盖现在/boot

 mkdir /tmp/boot  #然后再在/tmp下创建boot目录,用来保存再原一次boot.dump的原文件

 xfsrestore -f /srv/boot.dump -L boot_all /tmp/boot  #再还原一次boot.dump,将还原的文件保存到/tmp/boot下

 du -sm /boot /tmp/boot  #检查/boot与/tmp/boot的容量,看看差异,下面是打印的结果:

 #151    /boot
 #141    /tmp/boot  #为什么这个还原的文件容量不一样,比/boot要小一些?

 diff -r /boot /tmp/boot  #查看两个文件的不同数据:只在 /boot 存在:testing.img

命令的语法结构这里就不用解释了吧,直接来看最后还原的两个结果差异,在/boot下多一个testing.img,这个文件不就是boot.dump备份后添加的一个文件吗?也就是说xfsrestore还原的时候只会覆盖同名的文件,其他没有相对应的备份文件依然会保留。

接着来看还原增量备份文件

 mkdir /tmp/boot2  #在/tmp下创建一个boot2用来保存还原boot.dump1这个增量备份的原文件

 xfsrestore -f /srv/boot.dump1 -L boot_2 /tmp/boot2  #还原增量备份文件

 ll /tmp/boot2  #查看这个增量备份还原的文件信息:-rw-r--r--. 1 root root 10485760 6月  21 01:02 testing.img  #这里仅仅只有当初boot.dump1备份前新增的一个文件

通过上面的示例可以看到还原增量备份文件就只有当初备份时发生改变的文件,如果要想还原全部文件就只有将文件系统的初始备份文件和后面所有增量备份文件逐个还原,才能做到全部还原,当然也可以通过这种机制将文件系统还原到某个时期备份的节点。比如我要将/boot的全部文件系统备份还原到最后一个节点就可以在前面的示例基础上这样做:(将增量备份还原到之前还原初始备份文件的/tmp/boot目录下)

 xfsrestore -f /srv/boot.dump1 -L boot_2 /tmp/boot  #将增量备份还原合并到初始备份还原的/tmp/boot目录下

 du -sm /boot /tmp/boot  #然后再次检查/boot和/tmp/boot的容量差别

 #151    /boot
 #151    /tmp/boot  #通过对比这次的数据就会看到合并增量还原以后就一样了

以上就是xfsrestore的文件系统还原操作,但只是整个文件系统还原操作,有时候我们并不需要还原整个文件系统,所以xfsrestore同样可以实现还原自定的文件或目录,实现还原部分数据有两种方式,一种是通过-s选项指定要还原的文件或目录,另一种是通过-i的交互模式来实现还原部分数据,来看下面的具体示例:

基于-s选项还原指定的部分数据

 mkdir /tmp/root3  #创建一个目录用来保存还原文件

 xfsrestore -f /srv/boot.dump -L boot_all -s grub2 /tmp/boot3  #还原/boot中初始备份中的grub2

 ll -d /tmp/boot3  #查看还原的文件信息

基于-i的交互模式还原部分数据

 xfsrestore -f /srv/boot.dump -i /tmp/boot3  #使用交互模式还原数据(详细交互过程后面解析)

 子命令:ls  #列出当前目录下的文件名称

 子命令:add grub/  #这里要根据你测试的内容输入对应的文件或目录名

 子命令:add initramfs-3.10.0-1160.el7.x86_64.img  #这里要根据你测试的内容输入对应的文件或目录名

 子命令:extract  #开始恢复操作

 ll /tmp/boot3  #查看还原文件信息
 #总用量 31160
 #drwxr-xr-x. 2 root root       27 6月  13 00:21 grub
 #drwx------. 5 root root       97 6月  13 00:55 grub2
 #-rw-------. 1 root root 31904550 6月  13 00:55 initramfs-3.10.0-1160.el7.x86_64.img

这里有必要来看看-i的子命令:

ls:列出当前目录下的文件名称或指定目录下的文件名称
cd:切换到指定的目录下或该文件系统的根目录
pwd:打印当前目录相对于文件系统根目录的路径名
add:添加要还原的文件
delete:取消当前目录或当前目录下的文件的提取,即取消add的提取
extract:结束会话并还原指定的所有文件
quit:立即退出当前的交互操作,并不会执行还原操作
help:列出可用命令的帮助信息;

最后关于xfsrestore再给一个多余的补充,我在实际测试过程中忘了使用quit子命令退出,而是使用了【ctrl】+c强制退出,导致xfsrestore中断后续的xfsrestore命令不能正常进入,这时候可以有两个选择,使用xfsrestore [-f xxxx] -Q [xxx]将上一次文件系统中断的操作彻底退出,或者使用xfsrestore [-f xxxx] -R [xxx]继续上一次的文件系统操作直至完成。

 五、光盘写入工具

一般情况下现在用光盘备份数据的情况并不多,大部分情况下都会选择使用磁带来进行数据备份,磁带的容量高、存储时间长、耐摔等优点是光盘和其他备份设备不能比拟的,但作为服务维护还是有必要了解的,毕竟万一需要用到呢,然后就是练习一下如何创建镜像文件,这个应用还是比较多,下面就先来看如何建立镜像文件:

5.1mkisofs:创建镜像文件

 mkisofs [-o 镜像文件] [-jrv] [-V vol] [-m file] 待备份文件... -graft-point isodir=systemdir ...

实际上mkisofs是genisoimage这个命令的别名,在man的文档中关于这个命令的内容非常多,genisoimage这个命令是用来创建ISO9660/Joliet/HFS文件系统的,详细内容参考man的文档,这里我就简单的解析一下如何创建镜像文件,接下来来了解创建镜像文件的mkisofs选项和参数:

-o:用来设置生成的镜像文件名;
-J:产生兼容Windows的文件名结构,可增加文件名长度到64个unicode字符;
-r:通过Rock Ridge产生支持UNIX/Linux的文件数据,可以记录较多的信息(如UID/GID等);
-v:显示创建ISO文件的过程;
-V vol:建立Volume,类似Windows在文件资源管理器内看到的cd卷标;
-m file:用来指定不备份的文件,可以使用通配符(*);
-graft-point:可以用来定义镜像文件中的目录,简单的来说就是将当前Linux下的point文件存到镜像文件中的graft目录上(可能挂载不是合理的用词,但就是那个意思)

创建镜像文件测试示例一:

 mkdir /tmp/mirroring  #在tmp目录下创建一个存储镜像文件的mirroring的目录

 mkisofs -r -v -o /tmp/mirroring/system.img /root /home /etc  #将root、home、etc三个目录下的文件备份到镜像文件中,这里暂时不使用-graft-point

 ll /tmp/mirroring  #查看生成的镜像文件信息:-rw-r--r--. 1 root root 49469440 6月  21 20:49 system.img

创建镜像文件测试示例二:

 mkisofs -r -V 'linux_file' -o /tmp/mirroring/system.img1 -m /root/etc -graft-point /root=/root /home=/home /etc=/etc  #注意-graft-point选项的使用

 ll /tmp/mirroring/system.img1  #查看各个生成的镜像文件信息:-rw-r--r--. 1 root root 49475584 6月  21 20:58 /tmp/mirroring/system.img1

最后还是来在解释一下为什么要使用-graft-point,这是因为如果不使用-graft-point就会导致没有第一层目录,即镜像文件的根目录,如果没有根目录后面的数据就非常不好管理。

5.2刻录光盘之可启动光盘镜像文件制作

要刻录关盘之前,可能你会希望你的光盘放到光驱中开机以后就自动加载程序,相信你一定见过只要开机就自动安装到主机上的光盘程序,特别是使用光盘安装操作系统,只要一开机就自动开始安装操作系统。当然不是所有光盘都需要自动启动的光盘程序,有时候我们仅仅就是用光盘存储一些数据,那就不需要这样的功能,所以可不要把这个功能做到所有光盘镜像文件中。

制作/修改可启动光盘镜像文件

先准备一个CentOS镜像文件,使用一个最小的系统来做测试就好了(一般是带有Minimal的名称就是最小的,具体留意系统镜像文件的大小就可以了),如果没有可以到中科大镜像站这个地址下载:http://mirrors.ustc.edu.cn/centos/7/isos/x86_64/

 isoinfo -d -i /tmp/CentOS-7-x86_64-Minimal-2009.iso  #查看镜像系统的信息,确认要制作的镜像文件就是我们需要的,确认以后正式进入制作步骤

 mount /tmp/CentOS-7-x86_64-Minimal-2009.iso /mnt  #将系统镜像挂载到mnt临时挂载点上

 mkdir /iso/newcd  #这里创建一个newcd目录来保存值作的可启动镜像文件

注:这里需要注意,我这个根目录下的iso目录是挂载了一个独立的文件系统,千万别直接在根目录下创建这个iso来用,因为根目录一般默认没有可写权限,那样就没办法往里面写数据了。当然你也可以跟我一样挂在一个文件系统,但需要注意至少给root可写权限,默认挂载的文件系统可能没有可写权限,如果只有普通用户权限那你就要保证你可写权限。不然等下保存文件时就会报这个错误: error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1179) [sender=3.1.2] ,然后通过rsync命令将/mnt挂载点上的文件复制到/iso/newcd中:

 rsync -a /mnt/ /iso/newcd  #如果没报错的话就成功了

 ll /iso/newcd  #查看保存的文件

简单的来了解一下都有哪些文件:

ll /iso/newcd
总用量 76
-rw-r--r--. 1 root root    14 10月 30 2020 CentOS_BuildTagdrwxr-xr-x. 3 root root    35 10月 27 2020 EFI
-rw-rw-r--. 1 root root   227 8月  30 2017 EULA
-rw-rw-r--. 1 root root 18009 12月 10 2015 GPL
drwxr-xr-x. 3 root root    57 10月 27 2020 images
drwxr-xr-x. 2 root root   198 11月  3 2020 isolinux  //重要的相关文件在这里
drwxr-xr-x. 2 root root    43 10月 27 2020 LiveOS
drwxr-xr-x. 2 root root 28672 11月  3 2020 Packages
drwxr-xr-x. 2 root root  4096 11月  3 2020 repodata
-rw-rw-r--. 1 root root  1690 12月 10 2015 RPM-GPG-KEY-CentOS-7
-rw-rw-r--. 1 root root  1690 12月 10 2015 RPM-GPG-KEY-CentOS-Testing-7
-r--r--r--. 1 root root  2883 11月  3 2020 TRANS.TBL

重点来关注一下isolinux:

ll /iso/newcd/isolinux
总用量 60840
-r--r--r--. 1 root root     2048 11月  3 2020 boot.cat  //启动的安全编录文件
-rw-r--r--. 1 root root       84 10月 27 2020 boot.msg
-rw-r--r--. 1 root root      281 10月 27 2020 grub.conf
-rw-r--r--. 1 root root 55129656 10月 27 2020 initrd.img
-rw-r--r--. 1 root root    24576 11月  3 2020 isolinux.bin    //相当于启动引导程序
-rw-r--r--. 1 root root     3032 10月 27 2020 isolinux.cfg
-rw-r--r--. 1 root root   190896 11月  6 2016 memtest
-rw-r--r--. 1 root root      186 10月  1 2015 splash.png
-r--r--r--. 1 root root     2215 11月  3 2020 TRANS.TBL
-rw-r--r--. 1 root root   153104 10月 31 2018 vesamenu.c32
-rwxr-xr-x. 1 root root  6769256 10月 20 2020 vmlinuz    //Linux内核文件

然后来完成最后一步骤,生成可启动光盘镜像文件:

 cd /iso/newcd  #进入到newcd目录下

 mkdir /iso//mirroring  #创建一个目录用来保存镜像文件,下面就来正式生成可启动光盘镜像文件

 mkisofs -o /iso/mirroring/custom.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -V 'CentOS 7 x86_64' -boot-load-size 4 -boot-info-table -R -J -v -T .

 ll /iso/mirroring  #查看刚刚生成的可启动光盘镜像文件:-rw-r--r--. 1 root root 1081843712 6月  22 14:08 custom.iso

以上就是整个可启动光盘镜像文件的制作示例,最后一步就是将这个镜像文件刻录到光盘上,由于当前我没有光盘,没有办法演示,大概写一下刻录过程的思路。

5.3光盘刻录工具:cdrecord/wodim

在新版的CentOS中实现光盘刻录的命令是wodim,不过wodim兼容旧版的cdrecord,所以使用这两个命令都差不多,下面先来了解一下它的语法:

 wodim [options] track1... trackn  #这是man文档中的语法,wodim在文档中的描述就是:将数据写入光盘媒体

 wodim --devices dev=/dev/sr0...  #查询刻录机的bus位置

 wodim -v dev=/dev/sr0 blank=[fast | all]  #抹除重复读写盘

 wodim -v dev=/dev/sr0 -format  #格式化DVD+RW

 wodim -v dev=/dev/sr0 [可用选项功能] file.iso

光盘刻录命令wodim的选项解析:

--devices:扫描磁盘总线并找出可用的刻录机,后续的设备为ATA接口;
-v:在cdrecord运行的过程中显示过程;
dev=/dev/sr0:可以找出此光驱的bus地址,非常重要;
blank=[fast | all]:抹除可重复读写的CD/DVD=RW,使用fast较快,all较完整;
-format:对光盘进行格式化,但是仅针对DVD+RW这种格式的DVD而已;
[可用选项功能]主要是写入CD/DVD时可使用的选项,常见的选项包括有:
  -data:指定后面的文件file.iso以数据格式写入,不是以CD音轨(-audio)方式写入;
  speed=X:指定刻录速度,例如CD可用speed=40为40倍数,DVD则可用speed=4之类;
  -eject:指定刻录完毕后自动推出光盘;
  fs=YM:指定缓冲内存大小,可用在将镜像文件先暂时存至缓冲内存,默认为4m,一般简易使用8m,具体根据刻录机而定;
[针对DVD的选项功能]:
  driveropts=burnfree:打开Buffer Underrun Free模式的写入功能;
  -sao:支持DVD-RW的格式;
-dummy:实现刻录的选项;

查看光驱得设备信息,要确定有光驱,虚拟光驱也行。

 ll /dev/sr0  #查看你的光驱设备信息,一般sr0就是光驱设备名称

 wodim --devices dev=/dev/sr0 #查看光驱信息

接下来就是刻录得操作了,必须在有光驱得物理机上才能进行:

 wodim -v dev=/dev/sr0 blank=fast  #抹除光盘得原始内容(如果是可擦写的DVD就可以通过这个操作来抹除光盘上之前的数据)

 wodim -v dev=/dev/sr0 speed=4 -dummy -eject /iso/mirroring/custom.iso  #这是实现刻录的命令

关于实际刻录操作过程由于没法测试,可能涉及的操作问题我没办测试出来,不过大概流程就上面这样,以后在实际刻录操作中如果有相关问题我会来补充。

 六、其他压缩备份工具

 6.1转换和拷贝文件dd

关于dd这个命令在Linux操作系统(四):磁盘与文件系统的3.3.6中就有应用,当时是用来创建一个指定大小的空白文件,它在这篇博客中也是从文件备份的应用角度来解析,而它的真正作用就是用来转换和拷贝文件,这是man文档中的定义。说到这里你肯定迷糊了,dd到底是用来干嘛的?

围绕上面提出的文件,先来看看语法和它的选项都实现了什么,自然就明白它到底是用来做什么的了。

 dd  [--help] [--version] \
    [if=file] [of=file] [ibs=bytes] [obs=bytes] [bs=bytes] [cbs=bytes] [skip=blocks] [seek=blocks] \
        [count=blocks] [conv={ascii, ebcdic, ibm, block,  unblock,  lcase,  ucase,  swab,  noerror, notrunc, sync}]

dd的选项解析:

if=文件名:指定输入文件名或设备名,如果省略if则表示从标准输入读取(if是input file的简写,不是逻辑语句),说的直白点就是指定负责提供操作数据文件;
of=文件名:指定输出文件名或设备名,如果神略of则表示从标准输出输出(of是output file的简写),就是用来指定接收数据文件;
ibs=bytes:一次读bytes字节的数据,默认512;
obs=bytes:一次写bytes字节的数据,默认512;
bs=bytes:一次读和写bytes字节;
cbs=bytes:为block、unblock转换指定转换块的大小;
skip=blocks:在拷贝前,跳过输入文件的前blocks块,每块大小为isb-byte字节;
seek=blocks:在拷贝前,跳过输出文件的前blocks块,每块大小为obs-byte字节;
count=blocks:只拷贝输入文件的前blocks块,每块大小为ibs-byte字节;
conv={转换,转换...}:将文件按转换参数指定的方式转换(在","两边没有空格);
  ascii将EBCDIC转换成ascii;
  ebcdic将ascii转换成ebcdic;
  ibm将ascii转换成alternative ebcdic;
  block每一行输入的长度都是cbs-bytes字节,并且其中换行用空格替换;如果有必要,行尾会填充空格;
  unblock用换行替换每个输入块cbs-bytes(cbs字节大小)末尾的空格;
  lcase将大写字母转换成小写;
  ucase将小写字母转换成大写;
  swab用来交换每对输入字节,如果读入的字节数是奇数则最后一个直接复制输出;
  noerror发生错误时继续进行;
  notrunc不截断输出文件;
  sync用0填充每个输入块的末尾,使其块大小为ibs字节;

通过上面对dd的选项和参数了解,可以看到dd它的备份机制是直接备份磁盘扇区,它会有什么就备份什么,甚至可以用来将整个设备的内容都备份下来,所以比如要备份一个一摸一样的光盘、磁盘、都是没问题的。不过dd这种备份的缺点也很直接,就是它会将原设备数据一比一的备份出来,不论是否有数据,不论是文件系统还是文件数据都给备份出来,这有时候会浪费很多资源,但也是其优点,这样就不需要复杂的打包解包压缩解压缩逻辑处理,这是妥妥的用空间换时间。

正因为dd这种粗犷的备份方式,它的应用也十分简单,看起来语法好像很复杂,但实际上并不复杂,下面就通过几个示例来演示dd的使用:

 #dd示例一:将/etc/passwd备份到/tmp/passwd.back当中

 dd if=/etc/passwd of=/tmp/passwd.back  #这里执行会打印6+1读入和写入这样的信息,也可不能不是6,这个6指的是6个block

 ll /etc/passwd /tmp/passwd.back  #然后来查看言文件与备份文件的信息
 -rw-r--r--. 1 root root 3519 6月  13 00:54 /etc/passwd
 -rw-r--r--. 1 root root 3519 6月  23 11:13 /tmp/passwd.bac

由于示例中的注释内容写太多就不好查看了,这里来补充一下6个block的由来,因为我当前测试的passwd文件的容量是3519,而dd默认的block是512,那么3519/512=6.87···,所以表示使用了6个完整的数据块,和一个不完整的数据块,这里建议使用与备份文件所存储的文件系统数据块相同的block大小。

 #dd示例二:将光盘的内容备份成镜像文件

 dd if=/dev/sr0 of=/iso/mirroring/systemSrDD.iso

 #提问一:如果要将光盘中的某个文件备份出来呢?

 #解决思路:将光盘挂载到系统上,然后确定文件的具体路径,然后使用dd备份。

 #提问二:如果要将磁盘的某个分区备份到U盘呢?

 #解决思路:从U盘上划分一个差不多大小的分区出来(比如使用fdisk分区操作 fsisk /dev/sda),分区大小不能小于要备份的磁盘分区大小;接着不需要格式化操作,直接使用dd备份磁盘分区即可,比如要备份的是/dev/vda2,U盘的备份分区是/dev/sda1,那么实现备份的命令就是dd if=/dev/vda2 of=/dev/sda1,然后要清除dev备份过来的log(xfs_repair -L /dev/sda1),还有一个非常关键的数据就是文件系统UUID也被一起备份过来了,通过uuidgen生成一个新的UUID,然后将U上的备份分区UUID修改过来(xfs_admin -U 刚刚uuidgen生成的UUID /dev/sda1),到这一步就可以将U盘上的sda1这个备份分区挂载到系统上,你会发现他与dev2里面的文件是完全一样的。如果想在sda1上使用数据,还可以通过xfs_growfs dsa1的挂载点将U盘上的文件系统放大,是不是发现dd很强大,它可以直接将备份当作原数据来使用。

6.2存取归档中的文件cpio

cpio的备份程序需要配合其他程序以期实现,并且在实际应用中会应用到命令行上的逻辑语句,所以对掌握bash和shell才能很好的理解应用,这里就简单的介绍一下。其在man中的语法也是非常复杂的,这里用几个简化版的语法来介绍其应用和相关选项:

 cpio -ovcB > [file | device]   #备份

 cpio -ivcdu < [file | device]  #还原

 cpio -ivct < [file | device]     #查看

cpio的选项及参数解析:

备份使用到的选项和参数:
-o:将数据复制输出到文件或设备上;
-B:让默认的blocks可以增加至5120字节,默认是512,可以增加的好处是可以让大文件的存储速度加快(参考inodes的概念);
还原使用到的选项和参数:
-i:将数据自文件或设备复制出来到系统中;
-d:自动建立目录,使用cpio所备份的内容不见得会同在一层目录中,因此必须让cpio还原时可以建立新目录;
-u:自动的将较新的文件覆盖较旧的文件;
-t:配合i选项,可以用来“查看”以cpio建立的文件或设备的内容;
可以共用的选项或参数:
-v:在存储的过程将文件名打印在终端上;
-c:一种较新的portable format方式存储;

这里现不做任何解释,直接来看一个示例,然后基于这个示例来展开解析:

 cd /  #进入到根目录下

 find boot -print  #先通过find命令将boot目录下所有文件输出一次,find是实现递归处理层次目录中所有文件的程序,这里会将所有文件输出到终端上

 find boot | cpio -ocvB > /tmp/boot.cpio  #将boot下所有文件备份到/tmp下的boot.cpio中(注意这里没有在boot前面加根目录符号(/)

 ll -h /tmp/boot.cpio  #查看备份文件的信息

 file /tmp/boot.cpio  #查看boot.cpio的文件类型

以上的操作就是cpio的文件备份操作,这里来解释几个内容:

1."|"这里表示建立一个传输管道,将find获取到的数据通过一个管道源源不断的传输给cpio来处理;

2.大于号">"可以理解为将接收到的数据通过cpio处理以后存储到指定的文件中;

3.为什么要进入根目录下操作和为什么不在boot前面加根目录符号(/),这是因为如果携带了根目录符号,后面再使用cpio来还原时就直接会使用备份文件覆盖其目录对应的当前文件,这是非常危险的行为。但如果不使用根目录,cpio还原时就会在工作目录下新建一个boot目录来保存还原文件,所以还原也就不能在其原备份文件的目录上进行操作,比如这里的示例就不能在根目录下进行还原操作。

 然后来演示一下cpio的还原操作:

 cd ~  #进入root目录下

 cpio -idvc < /tmp/boot.cpio  #这个操作会将之前备份的文件按照原boot的目录层次结构,在当前root目录新建一个boot目录还原出来

 ll /root/boot  #查看还原后的文件信息

以上就是cpio的备份与还原的简单操作介绍,以后在实际的应用中如果发现相关操作有必要记录的内容都会来添加。

 

posted @ 2022-06-22 17:27  他乡踏雪  阅读(473)  评论(0编辑  收藏  举报