Linux下的文件打包和压缩

为什么要整理一下Linux下的打包和压缩工具呢?原因很简单,因为遇到问题了:游戏服务器可执行文件、配置和各种资源文件有4G多,每次在做版本的时候,编译完打包压缩要用掉10分钟多。我在上篇C++构建系统选择里面有提到过,200万行的代码编译用时不到10分钟,而现在一个简单的打包压缩竟然占用了10分钟,虽说这个步骤日常开发过程中很少操作,但每次凌晨做版本的时候,由于需求的变更,需要不断地构建、打包、压缩。做版本的同学苦不堪言,所有开发人员也得等着,这样浪费大家宝贵的时间是极度可耻的!遇到问题就要解决问题,问题解决了如果不记下来,下次遇到了又得去折腾了。下面进入正题。

虽说打包和压缩的原因各种各样,最重要的目的就是:减少文件的体积,从而节约磁盘空间和网络带宽。压缩文件的时候,最注重两个因素:速度压缩比。慢如蜗牛还是快如闪电?当然选择越快越好、压缩比越高越好。但是鱼与熊掌不可兼得,往往压缩比高的算法,需要的计算量就比较大,花费的时间就比较多。有没有加速的办法呢?

下面我会介绍一下我所熟知的Linux下的打包压缩工具,并做下对比,给出建议。上面遇到的问题,最后也会给出解决方法。

Linux下的文件压缩命令

打包和压缩工具概览

打包命令

Linux下的打包命令是tar,意思是:Tape Archiver。在计算机远古时代,打包后的文件会写到磁带(Tape)里面,所以才有了tar。而打包往往伴随着压缩,于是tar命令本身也支持多种压缩方式。

Linux下还有一个与此非常相似的命令ar,意思是:Archive。同为打包有啥区别了?
一般ar是用来打包目标文件生成静态库.a文件的,基本上不会用于普通文件的打包。

压缩命令

下面会对Linux下常见的压缩命令:zip, gzip, bzip2, xz, 7za进行对比。结果如下表:

命令 发布时间 压缩算法 压缩用时 解压用时 压缩后的大小
zip 1990 DEFLATE 2m43s 2m15s 796MB
gzip 1993 DEFLATE 2m34s 32s 796MB
bzip2 1996 Burrows-Wheeler 9m20s 2m1s 660MB
xz 2009 LZMA,LZMA2 28m31s 1m3s 474MB
7za 1999 LZMA,LZMA2 1m51s 52S 487MB

数据测试文件game.tar,大小为4G左右。下面为测试脚本:

tarfile=game.tar

echo "-------zip"
time zip $tarfile.zip $tarfile;
rm $tarfile
ls -lh $tarfile.zip
time unzip $tarfile.zip

echo "--------gzip"
time gzip $tarfile
ls -lh $tarfile.gz
time gzip -d $tarfile.gz

echo "--------bzip2"
time bzip2 $tarfile
ls -lh $tarfile.bz2
time bzip2 -d $tarfile.bz2

echo "--------xz"
time xz $tarfile
ls -lh $tarfile.xz
time xz -d $tarfile.xz

echo "--------7za"
time 7za a $tarfile.7z $tarfile
rm $tarfile
ls -lh $tarfile.7z
time 7za e $tarfile.7z

"压缩用时"、"解压用时"和"压缩后的大小"是用game.tar进行测试的。测试的机器CPU是32核,型号为:Intel(R) Xeon(R) CPU E5-2670 @ 2.60GHz

文件压缩

gzip

官方首页:http://www.gzip.org/

gzip, GNU的zip,是Linux的经典压缩工具,压缩后的文件后缀是.gz。采用的算法也是DEFLATE,该算法广泛应用于PNG图像、HTTP协议、SSH等。最大的优势就是速度快,压缩比还不错,几乎所有Linux系统都有安装gzip。

gzip压缩后的文件大小和.zip也差不多,压缩时间和zip相差不大,但解压缩的速度要明显高于zip。在Linux一般通过tar调用,很少直接使用。

压缩:

gzip game.tar   # 压缩文件
gzip -r  dir   # 目录下的所有文件进行递归压缩(目录下的所有文件都会生成.gz文件)

解压缩:

gzip -d game.tar.gz

bzip2

官方首页: http://www.bzip.org/

bzip2也是Linux系统常见的压缩方式,压缩后的文件后缀为.bz2。bzip2,基于Burrows–Wheeler algorithm,可以将文件压缩至10%-15%,解压用时比压缩用时快2-6倍。

gzip和bzip2实现算法不同,决定了它们各有优缺点:bzip2有比较高的压缩比,相应的压缩用时也要久一些,占用的系统内存也更大;gzip最大的优势就是压缩解压速度快,压缩比稍逊于bzip2。

压缩:

bzip2 file

解压缩:

bzip2 -d file.bz2

xz

官方首页:http://tukaani.org/xz/

xz是一个相对新的压缩命令,第一版是2009年发出来的。使用了LZMA2算法,该算法有这比高的压缩比,特别适用于对存储或带宽有严格要求的场景下,为了高的压缩比,压缩时间也是大大增加。

xz对压缩比和用时也提供了权衡的选项:

-0 ... -9 压缩预设,默认为6。
-e, --extreme 使用更多的CPU时间提高压缩比

压缩:

xz file

解压缩:

xz -d file.xz

PS. 使用xz时,要注意有些旧版本的Linux操作系统本身不支持,需要安装后才能使用。

zip

官方首页:http://www.info-zip.org/mans/zip.html

zip用于压缩,unzip用于解压缩,生成的文件格式是.zip。非常古老的压缩方式,压缩比比较低,好处就是由于古老,所以基本上是个操作系统都会默认对此进行支持。

虽然zip和gzip使用的算法都是基于DEFLATE,但具体文件格式是不一样的,所以.zip.gz文件是不兼容的。zip很少在Linux下使用,Linux下直接用gzip即可,多数情况都是其他平台下生成的.zip在Linux系统下面解压一下。

zip、7z和gzip、bzip2、xz还有一点不同的是,zip和7z本身支持打包,其他压缩命令仅是单纯的对单个文件或文件夹递归进行压缩。

压缩:

zip squash.zip file1 file2 file3  # 压缩文件
zip -r squash.zip dir1              # 目录打包并压缩

解压缩:

unzip squash.zip

7z

官方首页:http://www.7-zip.org/

7-Zip是一个有着高压缩比的打包压缩工具,提供了多平台(如:Windows、Mac、Linux等)支持,高压缩比也是得益于LZMA和LZMA2算法。上面的测试可以看出,7z和xz都是基于LZMA算法,但时间却天地之差,为何?答案是:7z是多线程的,压缩和解压并行计算。测试用的机器是32核的,在使用7z压缩解压时,CPU利用率达到3000%左右。

p7zip是Linux/Unix下7-ZIP的命令行版,命令是7za。7-ZIP并不是单纯的压缩工具,它支持多种压缩格式,在Windows/Mac有界面的系统下还有相应的GUI文件管理器工具支持。

7-ZIP的主要特点:

  • High compression ratio in 7z format with LZMA and LZMA2 compression
    Supported formats:
  • Packing
    • unpacking: 7z, XZ, BZIP2, GZIP, TAR, ZIP and WIM
      -Unpacking only: AR, ARJ, CAB, CHM, CPIO, CramFS, DMG, EXT, FAT, GPT, HFS, IHEX, ISO, LZH, LZMA, MBR, MSI, NSIS, NTFS, QCOW2, RAR, RPM, SquashFS, UDF, UEFI, VDI, VHD, VMDK, WIM, XAR and Z.
  • For ZIP and GZIP formats, 7-Zip provides a compression ratio that is 2-10 % better than
  • the ratio provided by PKZip and WinZip
  • Strong AES-256 encryption in 7z and ZIP formats
  • Self-extracting capability for 7z format
  • Integration with Windows Shell
  • Powerful File Manager
  • Powerful command line version
  • Plugin for FAR Manager
  • Localizations for 87 languages

压缩:

7za a  game.7z  gamedir

解压:

7za e game.7z

PS. 大多Linux下都没有安装7z,需要手动安装。

并行压缩和解压缩

压缩比和执行速度,鱼与熊掌两者兼得,如何做呢?上面也看到了7z利用多线程,执行LZMA算法也是很快就完成的。

开篇提到的问题是否也可以利用并行解决呢?由于各种原因,打包格式只能以.bz2的形式发布到运维系统,而bzip2的压缩速度实在是不敢恭维。bzip2的压缩过程是否可以并行执行?它的算法和文件格式支持的并行的话还好,不然也就没辙了,Google了一把,大神们已经准备了pbzip2,测试了一下,几乎被惊呆了:10min一下子只需要50s(32核E5处理器,4G文件大小)。

下面整理一下gzip、bzip2和xz及其并行版本的对比:

普通 vs. 并行 压缩用时 解压用时
gzip vs. pigz 2m34s vs. 0m11s 0m32s vs. 0m13s
bzip2 vs. pbzip2 9m20s vs. 0m40s 2m01s vs. 0m12s
xz vs. pixz 28m31s vs. 1m30s 1m03s vs. 0m6s

pigz

官方首页:http://zlib.net/pigz/

PIGZ – pigz,并行版本的gzip的实现 (Parallel Implementation of GZip),利用多线程来执行压缩,生成的文件和gzip完全兼容。解压缩的算法不可以并行化,为了加速,pigz在解压缩的时候创建了3个线程,主线程负责执行解压缩,其他的负责读写和检查计算,所以 解压缩速度比gzip也要快一些。

输入文件被划分成128KB大小的块并行执行压缩算法,然后按照顺序写到输出文件里,默认的块大小是128KB,也可以通过-b选项指定大小。执行压缩的线程数量,默认是机器中所有的CPU核心数量,也可以通过-p指定压缩线程的数量。

压缩:

pigz game.tar
```0

解压缩:

``` bash
pigz -d game.tar.gz

pbzip2

官方首页:http://compression.ca/pbzip2/

PBZIP2 – pbzip2,并行版本的bzip2的实现(Parallel implementation of the BZIP2),多线程压缩和解压缩,生成的文件和bzip2兼容,也即是说使用pbzip2生成的bz2文件,可以使用bzip2进行解压缩,反之亦可。pbzip2的解压过程也是多线程执行的,所以它的解压速度要快于pgiz。

块大小可以通过-1 .. -9-b#来指定,数字分别代表100k .. 900k(默认900k);线程数量可以通过-p#来指定,默认为机器中所有CPU核心。

压缩:

pbzip2 game.tar

解压缩:

pbzip2 game.tar.bz2

pixz

官方首页:https://github.com/vasi/pixz

pixz,xz的并行和带索引版(Parallel Indexing xz)。xz生成的.xz文件生成一大块压缩后的数据,pixz则生成一系列压缩后的可以随机访问的小块集合。pixz这种索引功能对于特别大的tarball文件特别有用,这样从压缩后的文件里面解压部分文件成为可能。比如在备份数据时候,可能10个G的压缩包,但当你使用此包时,仅需要其中的一个文件,xz则需要把10个G解压后取自己想要的文件,而pixz则直接可以指定解压需要的文件,没必要浪费磁盘和CPU。不过要使用索引功能的话,生成的文件后缀为.tpxz.xz不兼容的。

pixz和xz完全兼容,pixz的功能是xz的超集。听起来很不错吧!一般系统都不会安装此工具,源码安装时候依赖的包也有好几个:

  • pthreads
  • liblzma
  • libarchive
  • AsciilDoc

压缩:

pixz game.tar game.tar.xz   # 生成与xz兼容的格式
pixz game.tar           # 生成后缀为tpxz的格式,与xz不兼容

解压缩:

pixz -d game.tar.xz
pixz -d game.tar.tpxz

使用tar进行打包和压缩

上面所提到的压缩命令,gzip、bzip2、xz或并行版本的pigz、pbzip2、pigxz一般很少单独使用,多数时候都是在tar命令打包后执行压缩,合着tar一起使用。

tar本身支持的选项(xz老版本的tar可能不支持,需要更新哦!):

# 仅打包
tar cf  game.tar game-dir
tar xf  game.tar

# 打包后使用gzip进行压缩
tar cfz game.tar.gz game-dir
tar xfz game.tar.gz

# 打包后使用bzip2进行压缩
tar cfj game.tar.bz2 game-dir
tar xfj game.tar.bz2

# 打包后使用xz进行压缩
tar cfJ game.tar.xz game-dir
tar xfJ game.tar.xz

tar指定压缩工具(命令必须支持-d选项为解压):

# 打包后使用并行版本的gzip
tar -Ipigz -cf game.tar.gz game-dir
tar -Ipigz -xf game.tar.gz

# 打包后使用并行版本的bzip2
tar -Ipbzip2 -cf game.tar.bz2 game-dir
tar -Ipbzip2 -xf game.tar.bz2

# 打包后使用并行版的xz
tar -Ipixz -cf game.tar.xz game-dir
tar -Ipixz -xf game.tar.xz

压缩算法

关于压缩的工具,可谓五花八门。万变不离其宗,上面提到的工具用到的算法如下:

压缩算法涉及到一些数据知识和编码学,这里就不详细介绍了,有兴趣的同学自行Google。

小结

本文介绍了Linux下的常用的打包压缩工具:tar、gzip、bzip2、xz及其并行版本的基本用法,还有常用的zip7-ZIP的命令行版的基本用法,并逐个进行测试对比。

在Linux下面对于压缩格式的选择,我的建议是:

  • 临时性的压缩包尽量选择压缩速度快的格式,如:.gz。用于持久备份或存档的文件,尽量选择压缩比较大的格式,如:.bz2.xz
  • 大文件压缩时,尽量控制在5min以内,否则请尝试使用并行版本或将文件拆分为多份。
  • 尽量使用常见的压缩命令。7z虽然好处多多,Linux较少使用(记得Unix命令的设计哲学:只干一件事,把它做到极致,7z功能太多了)

参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280

推荐阅读更多精彩内容