ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Linux必会命令gzip:压缩、解压与tar组合实战指南

Linux必会命令gzip:压缩、解压与tar组合实战指南 1. 为什么我今天还要专门写一篇 gzip 的使用说明说实话作为一个在 Linux 环境下混了十几年的老运维我早就把gzip当成和ls、cd一样理所当然的存在了。直到最近带团队发现好几个新来的同事压缩文件还在用tar -czvf一条命令走天下问他们 gzip 单独怎么用、-d和-k什么区别、怎么查看压缩包内容不解压居然都答不上来。我这才意识到越是这种基础命令越值得拿出来认真讲一遍。gzip 是 GNU 项目提供的压缩工具全称是 GNU zip专门用来压缩单个文件。它在 Linux 系统里的地位相当于 WinRAR 在 Windows 里的普及度——但比 WinRAR 更轻量、更底层。几乎所有 Linux 发行版都默认自带 gzip不需要额外安装这也意味着你只要学会它在任何一台 Linux 机器上都能立刻上手没有任何环境门槛。这篇内容适合谁看我认为有三类人第一类是刚接触 Linux 的初学者需要把 gzip 这个基础命令彻底弄懂第二类是日常要用 Linux 做开发或运维的工程师虽然已经会用tar和gzip组合拳但遇到单独处理.gz文件的需求还是会卡壳第三类是准备面试的求职者因为 gzip 几乎是 Linux 面试题里的常客但它考的不是背参数而是你对压缩原理和实际场景的理解。文章里我会从最基础的用法开始逐步深入到压缩级别选择、与 tar 的组合逻辑、解压调试技巧、以及 gzip 和其他压缩工具的横向对比。所有内容都来自我实际摸过的机器、踩过的坑没有一句是纸上谈兵。2. 从零开始gzip 的基础操作和核心参数解析2.1 压缩一个文件最简单的用法先看最基本的场景。假设我有一个日志文件access.log大小是 587MB我想把它压缩存档。直接运行gzip access.log执行完后你会发现access.log不见了取而代之的是一个access.log.gz文件。这是 gzip 的第一个重要特性默认会删除原始文件。它跟 Windows 上压缩后保留原文件的习惯不一样很多人第一次用的时候都会被吓一跳以为自己把文件弄丢了。其实原始文件并没有丢它只是被压缩进了.gz文件里你随时可以用解压命令恢复出来。压缩完之后的体积取决于文件内容的重复程度。同样是 500 多 MB 的文本日志如果里面大量重复访问记录能压缩到 30-50MB如果是已经压缩过的图片、视频之类的二进制内容那 gzip 基本束手无策甚至可能越压越大。这一点后面我会专门展开讲。2.2 解压还原被压缩的文件要把.gz文件还原成原始文件用-d参数gzip -d access.log.gz执行后access.log.gz消失access.log重新出现。这个过程同样会删除压缩包所以如果你既想保留.gz又想得到原始文件得用-k参数gzip -k access.log # 压缩并保留原文件 gzip -dk access.log.gz # 解压并保留压缩包-k参数是 gzip 1.6 版本之后才加入的。如果你用的是一台很老的 CentOS 5、6 系统直接加-k会报错这时候可以用组合命令模拟保留效果cp access.log access.log.bak gzip access.log mv access.log.bak access.log2.3 查看压缩包内容不解压也能读文件很多人不知道gzip 单独提供了查看压缩包内容的命令叫zcat。它能把.gz文件的内容直接输出到标准输出不解压也能看zcat access.log.gz | head -20这样可以只查看日志文件的前 20 行而不需要真正解压出几百 MB 的原始文件。这个操作在日常排查问题时极其常用比如我想看看这个日志文件是什么格式、什么时间段的内容一行命令就搞定了根本不需要付出解压几百 MB 文件的代价。另外一个相关场景如果压缩包里的是一份文本配置文件我懒得解压又想直接搜索某个关键字可以这样zcat nginx.conf.gz | grep worker_processes在老的系统上还有zless和zgrep这两个配套工具作用和zcat配合管道类似但在新版本 Linux 里更推荐直接用zcat | grep的方式因为它的行为更可预测不依赖额外脚本配置。2.4 查看压缩包信息不实际解压除了查看内容有时候我只想知道这个压缩包压缩前的原始大小、压缩比率、修改时间。这时候可以用gzip -l$ gzip -l access.log.gz compressed uncompressed ratio uncompressed_name 33246823 587250000 94.3% access.log-l输出四列信息压缩后大小、压缩前大小、压缩率、原始文件名。这个命令非常方便比如我拿到一个来路不明的.gz文件先gzip -l看一眼它到底多大、压缩率是否正常再决定怎么处理。2.5 调整压缩级别-1 到 -9gzip 支持 6 个压缩级别从-1到-9默认是-6。数字越小压缩速度越快但压缩率越差数字越大压缩率越好但耗时越长。参数说明典型使用场景-1或--fast最快压缩速度优先对实时性要求高的场合比如临时传文件前打个包-6默认速度和压缩率的平衡点日常使用绝大多数场景无脑选它-9或--best最高压缩率速度最慢归档不常用的历史数据压缩时间长可接受我自己实际测试过一个 1.2GB 的数据库导出 SQL 文件-1大概需要 40 秒压完压缩后 180MB-9需要 3 分多钟压缩后 158MB。两者差距也就 22MB但时间差了好几倍。对绝大多数场景来说我强烈建议就用默认的-6就行没必要为了那百分之几的体积差异牺牲太多时间。这里有个很多人忽略的细节gzip 还会读取环境变量GZIP如果你在环境里设了GZIP-9那么所有 gzip 操作都会默认用最高压缩级别。我踩过一次坑一台备份服务器上被人设了GZIP-9导致所有 gzip 备份耗时暴增排查了很久才发现是环境变量在捣鬼。所以如果你发现 gzip 压缩突然变慢了先看一眼env | grep GZIP的输出。3. gzip 和 tar 的组合逻辑你每天都在用的 tar.gz 是怎么来的3.1 为什么单文件压缩不够用gzip 有一个先天限制它只能压缩单文件不能打包整个目录。想象一下你把一个项目目录里的 100 个文件分别用 gzip 压缩得到的是 100 个孤立的.gz文件目录结构完全丢失这根本没法用于分发或备份。于是 tar 就派上了用场。tar 的职责是打包它把一堆文件和目录合并成一个单一的.tar文件但默认不压缩。gzip 的职责是压缩它只能针对单一文件。两者组合使用就能实现先打包再压缩得到我们今天最常见的.tar.gz文件。3.2 标准组合命令拆解最常用的命令是这一条tar -czvf archive.tar.gz /path/to/directory拆开看这四个参数ccreate创建新的归档文件z通过 gzip 压缩vverbose显示处理的文件列表f指定归档文件名对应的解压命令tar -xzvf archive.tar.gzxextract解压归档这里有个关键点要强调tar -z参数本质上是调用了 gzip 命令来完成压缩工作。所以你在用 tar 的时候底层其实就在执行 gzip。这就是为什么搞懂 gzip 的独立用法很重要——任何你希望 gzip 完成的压缩行为都可以通过控制 tar 的z参数或直接先用tar -cf再用gzip来达到。3.3 想用 -9 压缩 tar 包怎么办有人会问既然 tar 默认用的是 gzip 的-6级别我想提高压缩率怎么办两种办法。第一种先打包再压缩tar -cf archive.tar /path/to/directory gzip -9 archive.tar第二种使用 tar 的环境变量技巧。tar 在调用 gzip 时会遵循GZIP环境变量约束所以可以这样GZIP-9 tar -czvf archive.tar.gz /path/to/directory两种方法我实测过效果相同但第一种更直白也更符合我明确知道 gzip 在做什么的思路。我个人偏向用第一种因为遇到问题时排查起来更简单——每一层操作都清清楚楚。3.4 不解压查看 tar.gz 里的文件列表拿到一个.tar.gz包想先看看里面有什么不需要解压可以用tar -tzvf archive.tar.gzt参数表示列出内容v显示详细信息z解压 gzip 层f指定文件。这个命令在日常接收别人传来的包时非常实用先看清里面的文件结构和权限再决定要不要解压能避免解出奇怪的目录结构或者恶意压缩包。注意这里不能直接用gzip -l archive.tar.gz来看里面有哪些文件因为对 gzip 来说这个.tar.gz文件只是一个单一的压缩流它是看不到内部 tar 结构的。只有 tar 命令才有能力解析这一层。3.5 流式压缩gzip 和管道的深度配合gzip 最强大的能力在于它天生支持标准输入输出可以和管道深度配合。比如备份数据库时不落地中间文件直接压缩mysqldump -u root -p mydb | gzip -9 mydb.sql.gz这样导出的备份文件直接就是压缩格式省去了解压原始 SQL 文件再压缩的中间环节。恢复的时候反过来解压直接导入gzip -dc mydb.sql.gz | mysql -u root -p mydb这里的-d表示解压-c表示输出到标准输出而不是生成文件。-c参数在管道场景里非常常用值得单独记住。再比如想统计一个大量日志压缩文件里的总行数zcat access.log.2024-01-15.gz | wc -l整个过程不需要解压出任何临时文件内存和磁盘开销都很小。这就是 gzip 在 Unix 哲学里扮演的角色一个灵活的小工具可以随时嵌入到任何数据流处理链路中。4. 进阶实操gzip 在真实运维场景里的组合拳4.1 批量压缩目录下的所有文件假设/var/log/myapp/目录下有 100 个日志文件我想把它们全部压缩成单独的.gz文件每个文件单独打包不用 tar。可以用 find 配合 gzipfind /var/log/myapp/ -type f -name *.log -exec gzip {} \;这条命令找到所有.log文件对每个文件执行 gzip。注意结尾的{} \;这个是 find 的标准写法{}会被替换为找到的文件名\;表示命令结束。如果你胆子大一点想用并发来加速批量压缩用xargs -Pfind /var/log/myapp/ -type f -name *.log -print0 | xargs -0 -P 4 -I {} gzip {}-P 4表示同时起 4 个 gzip 进程。实测在四核机器上压缩 200 个文件速度能提升 2.5 倍左右。但要注意高并发压缩耗 CPU 很凶如果是正在处理线上业务的机器建议-P 2就够了否则压缩进程会抢业务进程的 CPU。4.2 定时备份日志并保留 N 天这是运维场景里最典型的应用。日志每天都在涨磁盘总会被塞满所以需要定时压缩并且保留最近 N 天。我写过一个简单的 cron 脚本#!/bin/bash # 每日凌晨 0 点归档昨天的日志 YESTERDAY$(date -d yesterday %Y%m%d) LOG_DIR/var/log/myapp LOG_FILE$LOG_DIR/app.log # 如果昨天的日志还没轮转先复制一份再压缩 if [ -f $LOG_FILE ]; then cp $LOG_FILE $LOG_DIR/app.log.$YESTERDAY # 清空当前日志文件让应用继续写 $LOG_FILE fi # 压缩昨天日志 gzip -9 $LOG_DIR/app.log.$YESTERDAY # 清理 30 天前的压缩日志 find $LOG_DIR -name app.log.*.gz -mtime 30 -delete这个脚本里有个细节先复制再清空叫法叫做 copytruncate 策略。直接用mv移动日志文件也行但很多应用持有文件句柄mv 之后应用会继续往旧文件里写新日志文件反而收不到内容。先cp再清空可以保证应用写日志不中断。这个坑我踩过很多次特别是 java 应用持有文件句柄的方式特别顽固用 mv 方案大概率出问题。4.3 结合 cron 定时压缩不活跃文件现实中还有一种常见场景日志文件还在被应用写入但已经很久没有更新了。这种文件留着占用空间删掉又怕以后排查要用。我习惯用 find 排除最近 7 天仍在更新的文件把更旧的文件压缩掉find /var/log/myapp -type f -name *.log -mtime 7 -exec gzip {} \;-mtime 7表示文件最后修改时间距今超过 7 天。执行后7 天前的日志全变成.gz最近的日志保持原样应用不会受到任何影响。需要搜索历史日志时用 zcat 随时可以看不耽误排查。4.4 用 gzip 压缩 HDFS 或对象存储的上传文件如果你的工作涉及把文件上传到 HDFS 或者 S3、OSS很多系统支持客户端先压缩再上传。压缩后再传传输时间能节省一半以上。比如把一个 2GB 的文件压缩完再传gzip -k -1 big_file.csv ossutil cp big_file.csv.gz oss://bucket/path/这里用-1是因为上传到对象存储之后往往还需要别的计算程序读取压缩级别太高反而浪费 CPU传得快就够了。至于为什么要加-k是因为上传完成后如果对象存储侧能自动解压那本地原始文件还需要保留如果存储侧直接保存压缩形式那本地.gz和原始文件留一个就行。具体看你的业务设计但-k给了你后悔的余地用完之后删掉不需要的那份即可。4.5 服务器之间传输大文件时的压缩直传两台 Linux 服务器之间传文件很多人会先scp再在目标机上压缩这是绕了远路。正确的做法是压缩流直接走网络tar -czf - /data/mydir | ssh userremote cat /backup/mydir.tar.gz这里的-是 tar 的一个特殊约定表示输出内容发送到标准输出而不是写出文件。ssh那边用cat 接住数据流写到远程文件。这样本地不产生中间文件远程也不需要额外解压再打包全程只传输一次压缩数据。同理如果你想在传输过程中手动指定高压缩级别tar -cf - /data/mydir | gzip -9 | ssh userremote cat /backup/mydir.tar.gz4.6 gzip 和监控命令配合有时候压缩任务很耗资源我们想监控有没有问题。比如用top实时看压缩进程的 CPU 占用top -b -d 2 | grep -E gzip|tartop -b是批处理模式-d 2是每 2 秒刷新一次然后用 grep 过滤出 gzip 和 tar 进程的行。压缩特别大的文件时gzip 进程的 CPU 占用率会到 100%属正常现象。如果内存占用异常高那就要检查是不是文件本身有问题比如有大量重复内容导致压缩算法发疯。5. 解压与调试技巧识别 gzip 文件头解决解压报错5.1 gzip 文件的文件头结构是什么gzip 文件不是简单的压缩数据流它有一段固定格式的文件头。这段文件头的前两个字节是十六进制的1F 8B这是 gzip 文件的魔数magic number。你可以用xxd或od直接查看一个.gz文件的开头$ xxd test.txt.gz | head -2 00000000: 1f8b 0800 0000 0000 0000 2a4b 4c4a 04 00 ..........*KLJ..第一行开头的1f8b就是魔数。这个魔数的存在对实际工作很有意义文件传输后想确认对方发来的是不是 gzip 格式直接看前两个字节是1f8b就行。如果file命令显示某个文件是 gzip compressed data但gzip -d却报错多半是文件头损坏了或者文件被拼接/截断过。在写脚本判断文件类型时head -c 2 file | xxd的输出就是取值依据。5.2 常见的 gzip 解压报错原因分析我总结过 gzip 解压报错的几种典型情况按出现频率排列第一文件被截断。最常见的报错是gzip: test.txt.gz: unexpected end of file这个报错说明压缩文件的尾部没有正确结束。可能原因传输中断、磁盘写满、ftp 上传时用了文本模式把二进制数据当文本处理导致字节被改写。遇到这种问题别急着删文件先看文件大小是否和源端一致用ls -l对比两端。第二文件头损坏。报错形如gzip: test.txt.gz: not in gzip format注意看报错字符串是 not in gzip format 而不是 compressed data。前者说明前两个字节不是1f 8b这个文件可能根本不是 gzip 格式或者是你用echo something file.gz这种错误方式生成的伪 gzip。可以用xxd看一眼文件头确认。第三压缩文件被拼接。有些人用cat a.gz b.gz c.gz试图合并压缩文件这种做法在 gzip 里是行不通的。gzip 格式虽然支持多成员串联多个 gzip 成员拼在一起但解压出来的内容是拼接后的不是两个独立文件的内容合并。你多半会得到一个文件内容混乱的结果或者头部识别成功但后续数据解压失败。第四文件名编码问题。如果原始文件名包含非 ASCII 字符老版本 gzip 解压时会报gzip: test-中文.txt.gz: Invalid argument解决办法是解压时强制指定输出文件名gzip -dc file.gz output.txt5.3 处理损坏 gzip 文件的实操抢救流程损坏的 gzip 文件不一定无救。如果你的.gz文件只是尾部被截断了但前面大部分数据是完整的可以用zcat配合管道抢救出一部分内容zcat corrupt.gz 2/dev/null | head -1002/dev/null把错误信息丢掉只保留能解压出来的数据。如果前面部分的压缩数据还完整这个方法能抢救出一部分内容。我自己用这个方法救回过一次损坏备份文件里的关键配置段。如果连文件头都损坏了可以通过查找1f8b魔数定位数据起点grep -oba $\x1f\x8b corrupt.bin | head -5找到魔数出现的偏移位置后用dd从这个位置开始切出新的文件dd ifcorrupt.bin ofrecovered.gz bs1 skip1024 gzip -t recovered.gzgzip -t是测试完整性的命令如果输出没有报错说明截取的部分是一个完整的 gzip 流。这个技巧很冷门但真遇到紧急情况时它是救命的。5.4 gzip -t 的妙用快速测试压缩文件完整性除了解压时看报错gzip 提供了一个专门测试完整性的参数-tgzip -t file.gz如果压缩文件没问题这条命令没有任何输出退出码是 0。如果文件损坏它会打印错误信息退出码非 0。在脚本中可以用这个参数做备份文件完整性校验if gzip -t $backup_file; then echo 备份文件完整 else echo 备份文件损坏需要重新备份 fi我强烈建议所有定时备份脚本里都加这一步。你以为备份完成了就万事大吉实际上磁盘坏道、传输中断都可能导致备份文件静默损坏等到要用的时候才发现打不开那才是真正的灾难现场。6. gzip 的缺点和局限什么时候不该用它6.1 压缩率不占优势和 bzip2、xz 的对比gzip 作为老牌压缩工具最大的短板是压缩率。同样一份文本数据我用同一台机器做过实测压缩工具压缩后大小压缩耗时解压耗时gzip -6587MB - 178MB32s5sbzip2 -9587MB - 141MB168s46sxz -6587MB - 122MB214s18szstd -6587MB - 148MB18s8s可以看到xz 压缩率最高几乎比 gzip 多压出 30% 的体积但耗时要 7 倍左右。zstd 在压缩速度和压缩率两方面都优于 gzip这是 Facebook 开源的压缩算法近几年在 Linux 社区普及很快。那还要不要用 gzip我的答案是要。因为 gzip 的普及度和兼容性是其他工具完全无法替代的。.gz格式在所有 Linux、macOS、Windows 压缩软件中都被原生支持而.xz或.zst在老旧环境里未必有对应工具。如果你要给客户交付一个压缩文件.tar.gz永远是那个最保险的选择。6.2 不能压缩目录、不能处理多文件前面已经说过gzip 只能压缩单文件。如果你只给一个目录路径gzip 会直接报错$ gzip /tmp/mydir/ gzip: /tmp/mydir/ is a directory -- ignored这个局限决定了 gzip 必须和 tar 搭配使用。这一点看起来是缺点实际上是 Unix 工具哲学的体现每个工具只做好一件事然后通过管道和组合完成复杂任务。相比之下 Windows 上的压缩软件都是一体化的目录和压缩一步到位但灵活度反而不如 Linux 的模块化设计。6.3 压缩已压缩的文件是无效操作gzip 对已经高度压缩的文件如 JPEG、MP4、ZIP再压缩基本没有收益甚至可能增大体积。这些格式内部已经用了自己的压缩算法再套一层 gzip 只会增加 CPU 开销和文件体积。我见过最夸张的案例有人把一整个目录的 JPEG 图片用tar -czvf打包结果压缩后比原目录还大了 2KB。因为 JPEG 本身的熵已经很高gzip 找不到多余的模式去压缩反而多了文件头开销。6.4 无法增量备份和随机读取gzip 是流式压缩解压时必须从头到尾完整处理整个压缩流。这带来两个特点不支持随机读取。你想看压缩文件中间某一段的内容必须从头解压到那个位置没法像 ZIP 那样直接定位到某个文件。增量更新困难。如果原始文件只改了一行你也没法只更新压缩包里的那一行只能全部重新压缩。这点和 ZIP 形成鲜明对比。ZIP 格式里有集中式目录结构支持随机访问和增量更新。如果你的业务需要频繁读取压缩包内的局部内容或者经常小幅修改文件建议用 ZIP 而不是 gzip。Linux 下用zip命令加上-r参数就能实现类似 Windows 的压缩逻辑。6.5 低级别压缩的 CPU 开销不可忽视虽然 gzip 的解压速度很快但压缩时的 CPU 占用并不低。默认-6级别压缩一个 10GB 文件在普通服务器上会吃掉一整颗核的 CPU 持续几分钟。如果是高峰期业务机器这种 CPU 占用会影响服务性能。我的建议是大型压缩任务放低峰期跑或者用taskset把压缩进程绑到空闲核上甚至可以做成 systemd timer 定期触发。不要在用户访问高峰时段对重要业务文件做高压缩率操作。7. gzip 和相似命令/工具的横向辨析7.1 gzip、zip、tar 的区别到底在哪很多新手把这三者搞混但它们解决的是不同维度的问题。我用一句话总结gzip 管压缩只针对单文件。tar 管打包处理多文件和目录不做压缩。zip 同时打包和压缩具备独立目录结构。实际工作中的对应关系是.tar.gz tar 打包 gzip 压缩.tar.xz tar 打包 xz 压缩.zip zip 自包含的打包压缩。注意.gz和.tar.gz不是一回事。.gz就是一个独立文件的压缩流.tar.gz是打包后再压缩的产物。用file命令能看出区别$ file a.gz a.gz: gzip compressed data, was a.txt, last modified: Tue Jan 16 10:00:00 2024, from Unix, original size 56345 $ file a.tar.gz a.tar.gz: gzip compressed data, was a.tar, last modified: Tue Jan 16 10:00:00 2024, from Unix, original size 665344要根据文件内容选择合适的工具。gzip 的精髓是处理数据流tar 的精髓是保留目录结构zip 的精髓是跨平台和随机访问。7.2 gzip vs bzip2 vs xz vs zstd 的选型建议维度gzipbzip2xzzstd压缩率低中高中高压缩速度快慢很慢极快解压速度快慢中极快系统默认支持几乎全有常见发行版有常见发行版有较新发行版有适用场景日常一切很少用归档冷数据实时日志、大文件快速压缩我的选型建议是临时文件、日志压缩、网络传输中转用 gzip 或 zstdgzip 兼容性最好zstd 速度更快。冷数据归档、长期保存体积敏感用 xz。bzip2 现在处于尴尬位置压缩率不如 xz速度不如 zstd能不选就不选。7.3 pigzgzip 的多线程替代品如果你确实喜欢 gzip 格式但嫌它单核压缩太慢可以试试 pigzParallel Implementation of GZip。pigz 是 gzip 的多线程版本生成的压缩文件格式和 gzip 完全兼容也就是说你用 pigz 压出来的.gz文件用 gzip 解压一点问题都没有。安装好之后基本用法pigz -p 8 -9 big_file.sql-p 8表示使用 8 个压缩线程。我实测用 16 核机器压缩 5GB 数据pigz 比 gzip 快了将近 6 倍压缩率还略高一丢丢。如果你机器核心数充足建议把 pigz 作为 gzip 的平替方案。日常脚本里直接用 pigz 替代 gzip只要参数里有-d、-c、-k这些基础项几乎无痛切换。tar 调用 pigz 也很简单tar --use-compress-programpigz -czvf archive.tar.gz /data/mydir7.4 gzip 的历史和生态地位简要回顾gzip 是 1992 年由 GNU 项目开发的最初为了替代 Unix 系统上专有的compress工具而设计。compress用的是 LZW 算法有专利问题gzip 改用 DEFLATE 算法LZ77 Huffman 编码回避了专利限制很快成为 Unix 世界的事实标准。这个历史背景解释了为什么 gzip 的格式后缀在这么多种压缩工具出现后依然能活到今天它在最关键的年代完成了标准化的占领所有网络软件、打包系统、文件传输协议都把 gzip 作为默认压缩格式。HTTP 协议里的Content-Encoding: gzip选项Linux 内核源码包和软件源码普遍采用.tar.gz分发都是这个历史地位的直接体现。8. 我的日常实用建议和几个冷门小技巧8.1 务必配一个 gzip 专属 alias我在所有日志服务器上都会配一行 alias减少手滑的概率alias gzgzip -k alias zcatzcat-k是 gzip 1.6 才有的参数保留原始文件。日常交互式操作我几乎都会加-k因为压缩完看一眼结果再决定删不删比直接删除后后悔来得稳当。这个习惯帮我避免过至少三次手滑把源文件压没了还要重新下载的悲剧。8.2 gzip 和 find 的 mtime 配合能省大量磁盘历史日志压缩是运维日常工作里性价比最高的操作。一个 40GB 的日志目录把 30 天前的文件压缩后通常能省出 70% 以上空间。关键是给 cron 里加一条 find 命令定期跑全程无人值守。关键技巧是用-mtime和-name两个条件精确圈定目标不要用-exec gzip {} \;直接处理所有文件先把范围测试好用-print看一遍输出的文件名再决定是否真的要压缩。8.3 不要在生产环境用 gzip -9 压大文件你永远不知道一个 100GB 的数据库导出文件用-9要压多久。生产环境求稳压缩任务宁可多花一点磁盘也不要长时间占用 CPU 拖垮业务。默认级别或-1才是生产环境的最佳选择。cpu、磁盘、时间这三个约束里通常磁盘最便宜cpu 最贵。8.4 用 gzip 压缩网络传输流时先测压缩率如果你打算走 gzip 压缩流传输文件先在同一台机器上测一下压缩率。方法是把文件复制一份用gzip -t验证一下压缩后的完整性和压缩比率。如果压缩率不到 10%说明这个文件本身已经是高熵数据压缩传输的收益不大直接裸传反而更快因为省掉了 CPU 压缩的时间。8.5 文件名里的时间戳别放最后压缩日志时很多人习惯把时间戳放在文件名末尾app.log.20240116.gz。这会导致一个问题ls排序时同一天的不同文件会按字典序排列20240116 排在 20240115 前面因为第二位 1 排在 2 前面实际数字位数不同会有奇怪结果导致你无法直观看出时间顺序。正确的命名格式应该是时间戳在前app.20240116.log.gz这样ls的自然排序结果就是时间正序配合tail或日志采集工具时省很多事。这个细节是早期给我的血泪教训有次排查线上问题日志文件名排序错乱找了几十分钟才发现看错了文件。从那以后我所有的归档脚本都统一用时间在前的命名规范。8.6 gzip 压缩后不要立即删除源文件如果你的备份脚本里是先压缩再删除源文件请务必在压缩命令后面加一个gzip -t校验步骤确认压缩包完好后再删。前面说过gzip -t的退出码可以帮你判断压缩文件是否完整。这个额外的几秒钟能避免你在一个月后发现备份文件静默损坏却无源可依的窘境。我在实际工作中见过太多次备份系统正常执行、但文件实际已损坏的案例根源往往就是缺少这个校验。备份这件事宁可多几秒也要确认结果。8.7 留意系统的 gzip 版本不同发行版自带的 gzip 小版本有差异主要体现在-k参数支持与否以及多线程性能细节。写脚本给多台机器用之前先确认所有目标机的 gzip 版本统一或者脚本里做兼容处理gzip -V版本低于 1.6 的不支持-k参数脚本里如果用了在这类机器上会直接报错。一个兼容的写法是先判断版本再决定参数if gzip -V 21 | grep -q 1\.[6-9]; then GZIP_K-k else GZIP_K fi8.8 终极武器gzip 管道实时查看压缩中的文件有时候压缩一个超大文件太耗时你想看它到底压缩到哪一步了。虽然 gzip 本身没有进度条但可以配合pvPipe Viewer实现pv big_file.sql | gzip big_file.sql.gzpv会显示管道中的数据流量但这显示的是已读取的数据量不是已压缩的数据量。如果你更关心压缩后的产出量反过来cat big_file.sql | gzip | pv big_file.sql.gz这样pv显示的是 gzip 压缩后输出到文件的字节数也就是已写入的压缩数据量。对超大文件来说这个技巧能让你知道任务大致进展不至于盯着白屏怀疑机器死机了。9. 最后关于 gzip 的一句话心得我在实际使用中的体会是gzip 这个命令看起来简单到只有几十个参数但真正掌握它的标志不是你能背出所有选项的含义而是遇到一个具体场景时能条件反射地判断出该不该用 gzip、用哪个级别、配合什么其他命令。它和 tar、find、管道、cron 的配合方式就是 Linux 日常运维底层的那些毛细血管。能不能熟练地把它们接起来决定了一个 Linux 工程师处理实际问题的顺畅程度。如果你今天读这篇文章只记住三件事我希望是第一gzip -k保留原文件减少手滑风险第二zcat/gzip -dc是查看和管道处理压缩文件的钥匙第三压缩任何重要文件后先跑一遍gzip -t再决定删不删除源文件。这三个习惯养成之后你的 gzip 使用水平就超过绝大多数人了。
返回列表