2011年7月25日星期一

如何制作硬盘备份的压缩镜像?dd和gzip

我在《dd: 穷人的硬盘备份与恢复工具》中分享了如何做硬盘的镜像备份和硬盘恢复的小经验。不过,光用dd指令做硬盘备份,那么备份镜像文件占据的空间和源盘空间一模一样。较新的机器,不少内装的硬盘高达500GB或1TB。那么备份USB盘就需要有相应的空间。其实,硬盘上有许多未用空间,把未用空间也原样备份实在是资源浪费。我们不妨把镜像备份压缩起来。

在《dd: 穷人的硬盘备份与恢复工具》一文中我们知道如何用dd作镜像备份。我们用的指令类似于:

dd if=/dev/sda of=/media/sdc1/yourBackupDir/BACKUP.img bs=512k &


而现在,要制作压缩镜像备份,我们得把dd和gzip指令结合起来。以下是制作压缩镜像备份的指令:

dd if=/dev/sda ibs=512k | gzip > /media/sdc1/yourBackupDir/backup.gz


我解释一下指令。

if 跟随的是输入文件。这里输入文件是device下面的整个硬盘sda

这里我们不见了of(输出文件),而代之以另一个程序,叫gzip的压缩程序。dd程序的输出被送往gzip,成了gzip的输入。通过gzip的压缩,它的输出被记录在文件backup.gz中。文件backup.gz的路径是挂载于/media下的USB硬盘sdc1的文件夹yourBackupDir。

用这个指令,可以大大减少备份的空间。我的一台Lenovo台式电脑配备300GB的硬盘,安装WINDOWS XP、大量Lenovo随机软件和小孩的游戏软件。经过gzip的压缩,备份被压缩在60GB左右。我自己使用的Lenovo S10-2 Netbook,配备160GB硬盘,安装WINDOWS XP、Lenovo随机软件,TradeStation 8,OpenOffice,以及第二个操作系统“红旗Linux 6.3”。它的压缩镜像备份是22.3GB。

那么,压缩的镜像备份如何恢复呢?硬盘恢复的指令是:

gzip -dc /media/sdc1/yourBackupDir/backup.gz | dd of=/dev/sda obs=512k &


这条指令的意思是:

gzip的输入是存于硬盘sdc1中的压缩镜像备份backup.gz。gzip 的 -d 表示解压缩;-c 是把输出写到标准输出端(通常是屏幕)。然后把gzip的输出作为 dd 指令的输入。而dd指令的输出则是硬盘sda。 dd 指令的 obs=512k 表示 dd 的输出缓冲是512k。就是说 dd 等待gzip的输入,积累到了512k之后才向硬盘sda写一次。

用dd和gzip结合的方法压缩的效果不错。不过对于使用多年的机器,压缩效果就不如新的时候那么好了。这是为什么呢?

我们知道,文件压缩的原理是建立一个索引表,用较短的字符串来替代较长的字符串。比如字符串:

“This_is_a_test._This_is_a_test._This_is_a_test._This_is_a_test._”(我在这里用_表示空格,以便看清楚)。

如果我们从左到右逐字扫描第一个重复是is_。在索引表里我们建立第一个替代:
1 3 3 (第一目索引从第三个位置起,长度为3,即is_所在的位置)

这样,我们的字符串就可以写成:

“This_1a_test._This_1a_test._This_1a_test._This_1a_test._”

我们接着扫描:“This_1a_test._” 又有重复。于是索引表就成了:
1 3 3
2 1 14 (第二目检索从第一位起,长度为14)

于是,字符串可以些成:

“This_1a_test._222”


然后把检索表加在压缩文件后面,就形成了压缩文件。所有文件的储存最终都是2进位制的0和1的数字,重复率很高,所以压缩很有效。


复原时,反向运作即可复原。


当然,这只是简单说一下无损压缩的原理。每个压缩软件都有可能有不同的做法。我们用的gzip具体怎么工作的,我也不清楚。有兴趣可以查看gzip的源码。了解原理的目的是为了说明我的应用。


在前面解释文件压缩原理的那个例子中,我们看到,一个文件重复的字串越多,重复的字串越长,那么压缩效果越好。未写过的空间原本都是2进位的0,会有很长、很多的重复,有利于压缩。然而,在我们使用计算机的过程中,我们不断新建文件,不断删除文件,不断把文件来回复制、删除或下载、删除。操作系统本身也不断生成各种文件,用完后又删除。这些看似被删除的文件其实并没有真的被删除。操作系统只是在文件管理系统的检索表中把文件名的头一个字母抹掉。这样做,一是为了删除的操作快,二是为了万一用户后悔,数据可以尽可以多地恢复。操作系统在创建新的文件时,会尽可能写在完全未被使用过的空间,而不是写在已经抹掉的文件空间。这也是为了万一需要被删除的文件尽可以多地恢复。但这个做法对压缩却不利的因素。因为原来未写过的空间一色清的2进位0,现在可能被各种文件写过后,重复率降低,从而降低了压缩的效率。


我们有没有办法提高压缩效率呢?有。答案还是能在dd指令中找到。那就是,先用dd指令把硬盘所有未用空间写成0,这样已被删文件的空间就重新被0占据。这个指令是:

dd if=/dev/zero of=/media/sda1/zerofile bs=512k &


它会建立一个命名为zerofile的文件(你可以给任何文件名),dd会用0写这个文件,直到这个文件占据逻辑硬盘sda1中所有的剩余空间,无法再写为止。之后,删除这个zerofile,你就把所有未用空间重新归0了。归0之后再作硬盘的镜像压缩备份,那么备份就会小很多。

Read more: 如何制作硬盘备份的压缩镜像?dd和gzip - 老石的日志 - 贝壳村 -

没有评论: