恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
tar命令从入门到进阶:归档压缩、增量备份与自动化实战
首页
资讯中心
/
tar命令从入门到进阶:归档压缩、增量备份与自动化实战
tar命令从入门到进阶:归档压缩、增量备份与自动化实战
发布时间:2026/10/14 4:18:00
坦白说用了这么多年Linuxtar大概是除了cd和ls之外我敲得最多的命令之一。不管你是刚接触命令行的新手还是天天跟服务器打交道的老人tar都是绕不过去的基础工具。它负责把一堆文件打包成一个归档文件也能从归档里把文件还原出来配合上压缩算法之后传输、备份、分发都靠它。很多教程把tar讲得太零碎了网上一搜全是“tar -czvf是什么意思”之类的碎片答案真正遇到问题的时候还是不知道怎么组合。这篇我打算从最基础的用法一路讲到处理大规模数据时的高阶技巧全程用实操案例说事。适合刚入门的读者一步步跟练也适合有经验的开发者查漏补缺。1. 先搞清楚tar到底在干什么1.1 打包和压缩是两回事很多人最早接触tar的时候都以为它是个“压缩命令”其实严格来说它是个“归档命令”。归档的意思是把多个文件和目录合并成一个单独的文件方便传输和存放。而压缩是在归档的基础上用算法把文件体积变小。用一个生活化的类比来说把衣服叠好装进一个行李箱这个过程是归档用真空压缩袋把棉被抽气压扁这个过程才是压缩。tar负责装箱gzip、bzip2、xz这类工具负责抽气。它们俩经常一起出现因为tar内置了调用压缩工具的参数于是大家习惯性地把tar当成一个压缩命令来用。理解这个区别很重要因为它决定了你遇到一些诡异问题时的排查方向。比如说你写了一个tar命令去解压某个文件结果提示“compressed with unknown algorithm”这时候如果你知道tar本身不认识这个压缩格式需要指定对应的解压参数就不会一头雾水。1.2 为什么tar在Linux生态里地位这么高Unix系统的哲学是“每个程序只做好一件事”tar和压缩工具的分工协作正是这种哲学的体现。在Linux世界里几乎所有的软件源码包都以.tar.gz或.tar.xz的形式分发系统初始化脚本里的备份逻辑也大量依赖tar。更重要的是tar可以保留文件的权限、属主、时间戳等元信息这在备份和迁移场景里是硬需求——你用zip压缩再解压可能所有文件都变成了当前用户的权限但用tar打包解压出来还能保持原来的权限和属主信息。另外tar命令有一堆非常灵活的参数组合可以直接接管道、远程传输、增量备份这些能力叠加起来让它在自动化场景里几乎无法替代。学会了tar你的Linux技能树才算真正点了基础分支。1.3 本机环境说明后面所有示例在我本地验证过环境是CentOS 7.9和Ubuntu 20.04双系统GNU tar版本是1.29/1.30。大部分命令在macOS上也能直接用但还是有一点区别具体差异我在对应位置会提醒。2. 最常用的参数组合看这一节就够了2.1 记住这几个操作用的字母tar的参数可以分成两类一类是你要执行的操作一类是你要附加的选项。操作类的字母有几个请你重点记住这几个-c创建归档也就是打包。-x解包把归档拆出来。-t列出归档里的文件列表不解包。-r向已有归档追加文件。-u更新归档仅添加比归档里更新的文件。附加选项里面最常用的是-f表示操作对象是一个文件而不是标准输入输出。很多老遇到“No such file or directory”的新手就是因为忘了写-f。然后就是压缩格式相关的-zgzip、-jbzip2、-Jxz。一个非常容易混淆的点tar -czvf、tar -xzvf这些写法里字母前面的-其实可以省略。GNU tar支持tar czvf这种写法也支持tar -czvf这两种在Linux上都能跑。但老牌的Unix系统上可能会有差异所以我的建议是养成写短横线的习惯跨平台更安全。2.2 打包一个目录假设你的项目目录叫myapp里面有代码、模板、配置文件现在要把它打包成myapp.tar.gztar -czvf myapp.tar.gz myapp/拆开来看-c表示创建-z表示用gzip压缩-v表示显示进度把正在处理的文件名打到屏幕上-f指定生成的归档文件名。命令的最后是你想打包的路径。如果你打包的是当前目录下的内容而不是目录本身要注意路径写法。tar -czvf myapp.tar.gz .会把当前目录所有内容打包不包含外层目录名。tar -czvf myapp.tar.gz myapp/则会把myapp这个目录本身也放进归档。这个区别在你解压的时候体现得很明显前者解压出来是散落的一堆文件后者解压出来是一个完整的myapp/目录。2.3 解包并还原解包呢就是把上面命令里的-c换成-xtar -xzvf myapp.tar.gz默认会在当前目录下解出归档里保存的所有文件。如果你想解压到指定目录加一个-C参数tar -xzvf myapp.tar.gz -C /tmp/restore/-C的意思是切换目录相当于先执行cd /tmp/restore/再解压。注意这个目录必须已经存在tar不会自动帮你创建不存在的目标目录这是新手最容易踩的一个坑。2.4 只查看归档里的内容不解包要确认一个tar包里的文件结构不需要解压用-ttar -tzvf myapp.tar.gz-t列出归档里的所有条目加上-v会显示权限、属主、大小、时间等详细信息相当于看到一份归档的目录树。这个操作在你想从一堆老包里找某一个配置文件时特别有用省得解压出来翻一遍。2.5 只解压归档里的某一个文件有时候你只需要归档里的一个文件比如日志包里的某一天日志完全没必要全部解压。tar支持指定文件名解压tar -xzvf logs.tar.gz 2024/01/15/access.log注意这里的路径要跟归档里的路径完全一致你可以先用-t查看确切的路径再去解压。归档里如果有几百个文件只解压一个的速度会快非常多。3. 参数选型背后的原理为什么有的命令慢得离谱3.1 gzip、bzip2、xz怎么选上面提到了三种压缩格式这里展开说说它们之间的取舍。gzip是历史最悠久、兼容性最好的压缩方式压缩速度快压缩率中等。xz的压缩率最高能把文件压得更小但压缩和解压过程都非常慢对CPU的消耗也大。bzip2介于两者之间但在这个领域的位置比较尴尬虽然压缩率也不差但速度比gzip慢压缩率又赶不上xz所以实际使用频率越来越低。选哪个取决于你的场景。临时传个文件用gzip就够了做长期归档、希望占空间最小用xz传输大文件想省带宽当然也考虑xz但要注意压缩时间可能比传输时间还长。举一个我经历过的例子一份20GB的数据库备份文件用gzip压缩用了6分钟生成的文件是3.2GB用xz压缩用了40多分钟生成的文件是1.9GB。如果只是临时转存多花三倍时间换那1.3GB的省量完全划不来。直接用tar的-J参数来走xztar -cJvf backup.tar.xz /data/3.2 压缩级别怎么调压缩工具都支持调整压缩级别通常范围是1到9。数字越大压缩率越高耗时和CPU占用也越高。gzip的默认级别是6xz的默认级别是6但xzgzip的最高是9。tar里可以通过--use-compress-program传递额外的参数也可以直接用环境变量。我的习惯是日常打包用默认级别就够了不折腾。但如果要传大文件我会把gzip级别调到1或2因为压缩率变化不大速度却能快上好几倍tar -cvf - /data/ | gzip -1 backup.tar.gz这里用管道的方式先把tar的输出送到gzip再重定向到文件。理由是tar的-z参数没办法直接指定压缩级别但单独调用gzip就能灵活控制。3.3 归档格式的兼容性问题tar的配置文件格式有好几种GNU tar在老系统上可能会默认生成一种叫“GNU格式”的归档它在文件路径过长、文件过大时用了扩展头处理但新版本tar读老格式没问题反过来老版本读新格式可能会警告。如果你的归档要分发给各种老旧系统使用尽量用--formatposix或--formatustar保兼容性。tar --formatposix -czvf backup.tar.gz /data/不过这个需求越来越少了现在的Linux发行版基本都是GNU tar 1.30以上兼容性早就不是问题。除非你接的特殊设备否则不用太操心。4. 实战场景搭建一个靠tar支撑的自动化备份链路4.1 按日期滚动备份做运维的都清楚备份文件必须带时间戳不然恢复的时候根本分不清哪个是最新的。我习惯用date命令动态生成文件名#!/bin/bash backup_dir/backup target/var/www/myapp date_suffix$(date %Y%m%d_%H%M%S) tar -czvf ${backup_dir}/myapp_${date_suffix}.tar.gz ${target}也可以用$(date %Y%m%d)只保留日期一天备份一次。放在cron里每天凌晨执行配合日志清理策略这就是最简单的备份轮转方案。在cron里执行时有个坑——cron的环境变量跟交互式shell不一样tar的路径建议写全或者脚本开头先source /etc/profile。4.2 增量备份的正确姿势日常备份如果每次都全量打包数据量大了之后不仅浪费空间耗时也会越来越长。tar支持一种基于快照文件的增量备份模式# 第一次全量备份 tar -czvf backup_full.tar.gz -g snapshot.snar /data/ # 第二次增量备份 tar -czvf backup_inc1.tar.gz -g snapshot.snar /data/ # 第三次继续增量 tar -czvf backup_inc2.tar.gz -g snapshot.snar /data/-g指定一个快照文件tar会记录每个文件的访问状态和修改时间。第一次执行时快照不存在所以是全量备份第二次、第三次执行时tar对比快照文件只把新增或修改过的文件打进去。恢复的时候要按顺序先恢复全量再依次恢复每个增量包。增量备份的注意点在于快照文件snapshot.snar必须小心保管丢了的话后面的增量包就恢复不了了。这个文件很小但它的作用就像链表的节点——断了一个后面全断。所以备份策略里快照文件本身也应该被单独保存和保护。4.3 用管道实现远程备份很多时候数据不在你手头这台机器上你想把A服务器的数据打包到B服务器可以先ssh过去跑tar再把输出流拉回来或推过去。ssh user192.168.1.101 tar -czvf - /data/project local_backup.tar.gz这里的-表示把tar的输出写到标准输出而不是某个文件。ssh在远端执行命令把命令产生的标准输出传输到本地本地把这个流重定向成文件。这比先打包再传文件少了一步盘上读写磁盘IO压力小。反过来把本地数据传到远端并解压tar -czvf - /data/project | ssh user192.168.1.102 cat /backup/project.tar.gz或者干脆直接解到远端tar -czvf - /data/project | ssh user192.168.1.102 tar -xzvf - -C /backup/restore/这种玩法是tar和管道协作的精髓。理解了这种思路之后你会发现tar不仅能跟ssh组合还能跟其他命令组合变成一条简洁的数据流水线。4.4 排除不需要打包的文件打包一个大目录时通常要跳过一些不需要归档的文件或者目录。比如项目里的node_modules、cache、logs这些目录又大又没必要备份。tar提供了两个实用的排除参数tar -czvf project.tar.gz --excludeproject/node_modules --excludeproject/cache /home/user/project/注意排除路径的写法有讲究。如果你打包的是/home/user/project/那么排除项要写project/node_modules也就是归档内的相对路径。如果你直接在路径里带上绝对路径写--exclude/home/user/project/node_modules很多时候也不生效这个坑我踩过好多次。最稳妥的方式是切换父目录打包然后用相对路径排除cd /home/user tar -czvf project.tar.gz --excludeproject/node_modules --excludeproject/cache project/另外还有一种用通配符的排除方式tar -czvf project.tar.gz --exclude*.log /home/user/project/会跳过所有以.log结尾的文件。如果排除规则多建议写成一个排除文件用-X参数读入tar -czvf project.tar.gz -X exclude_list.txt /home/user/project/exclude_list.txt里每行一个排除模式以#开头的是注释。模板如下# 排除日志 *.log # 排除缓存目录 project/cache project/tmp这个文件化管理方式最适合长期稳定的备份任务规则全在文件里改起来也方便。4.5 分卷压缩打包大文件到多个小卷如果你要把一个大目录打包后刻录到光盘或者传到U盘但U盘单个文件限制4GB这时候就需要把归档拆分成多个小文件。tar本身不做分卷需要配合split命令tar -czvf - /data/bigdata/ | split -b 2G - bigdata.tar.gz.part.输出文件会是bigdata.tar.gz.part.aa、bigdata.tar.gz.part.ab、bigdata.tar.gz.part.ac这样依次排列。合并的时候用cat拼回来cat bigdata.tar.gz.part.* bigdata.tar.gz tar -xzvf bigdata.tar.gz顺序必须保持正确split按aa、ab、ac排列cat用通配符依次读取没问题。如果要更保险可以用split -d配合数字后缀不过通配符展开已经够稳了。5. 排查与异常处理tar用多了就懂的那些坑5.1 路径里的“./”让解包目录变得奇怪有些归档解压出来你会看到文件都带着./前缀比如./etc/nginx/nginx.conf。这是因为打包时用了相对路径。这种包解压是没问题的但看着乱。避免的办法是打包时尽量在目标目录的父目录操作用相对路径打包。如果你收到这种带./的包想规整处理可以用--strip-components裁掉路径层级。假设一个包里的路径是opt/myapp/config/nginx.conf你只想解压出config/nginx.conf不想要前两级目录tar -xzvf backup.tar.gz --strip-components2这是解决“解压出来一堆嵌套目录”问题的利器。要注意数字2表示裁掉前2级路径按实际需要调节。5.2 一个文件在打包时发生变更导致校验问题生产环境里你打包一个正在运行的目录时很可能有进程正在写文件导致出现“file changed as we read it”的警告。tar默认会继续打包但会在退出码里标出异常。处理办法有两个一是打包前先停服务二是用tar的--ignore-failed-read但注意选项行为有限或者干脆接受警告只要退出码不是1就还能用。有个比较极端的方案是结合--warningno-file-changed参数tar -czvf backup.tar.gz --warningno-file-changed /var/lib/mysql/意思是不把这个警告视为异常。可以用但我还是建议数据库这类文件先用工具做快照再用tar打包快照目录更稳妥。靠tar的warning控制只是权宜之计。5.3 解压时提示“Permission denied”权限问题是初次使用tar最常踩的坑。归档里的文件可能属于某个用户你当前用户没有权限写入目标目录解压就会报Permission denied。常见的场景是用普通用户解压由root创建的包到/usr/local这类目录。解决方式要么用sudo要么解压到自己的家目录再用sudo移动。还有一点如果你以root身份解压别人打包的包会很自然地改变文件属主这在恢复环境时要多留意。5.4 “Cannot open: No such file or directory”是怎么回事这个提示通常有两个原因一个是目标目录不存在一个是归档里解压出的路径包含不存在的父目录。前者用-C之前先确保目录存在后者一般不会发生tar会自动创建路径中的目录。真正需要担心的是如果归档中有绝对路径比如/home/user/file.txt解压时会直接写到根目录下的绝对路径不再受-C目录的影响。从这个角度说打包的时候用相对路径是更安全的习惯。5.5 检查tar包是否完整在传完一个大包之后最好先确认一下归档文件没有损坏。一个快速的验证方式是tar -tzf backup.tar.gz /dev/null如果归档有损坏这个命令会报错。如果是gzip格式的包你还可以先单独检查gzip完整性gzip -t backup.tar.gzgzip -t专门测试gzip压缩流的完整性exit code为0表示没有损坏。先把压缩层验证一遍再做tar层验证双保险。6. 进阶玩法tar跟其他工具的组合技6.1 按文件大小、时间筛选后打包有时候你只想把某个目录下最近7天内修改的文件打包传统做法是先find再tar。find的输出作为参数传给tar有两种主流方式。第一种是借助xargsfind /data/project -name *.log -mtime -7 -print0 | xargs -0 tar -czvf logs.tar.gz用-print0和-0是为了避免文件名里有空格导致的切词问题。第二种是tar自身的-T参数从一个文件读取待打包文件列表find /data/project -name *.log -mtime -7 filelist.txt tar -czvf logs.tar.gz -T filelist.txt注意-T的参数是包含文件列表的文件每行一个文件。这两种方式我个人更推荐第二种因为事后可以保留filelist.txt作为备份清单备查。而且-T还能配合进程替换(...)直接在命令行里生成临时列表tar -czvf logs.tar.gz -T (find /data/project -name *.log -mtime -7)这段在bash和zsh里都能跑非常干净。6.2 用tar做磁盘间迁移服务器上数据目录迁移到另一块磁盘时用cp -a或者rsync都行但tar在数据量特别大、文件特别多的时候表现也相当稳。硬拷贝一大片文件到新盘inode和权限不容易完全对齐而且碎片多。有一种老派的迁移手法cd /old/data tar -cf - . | tar -xf - -C /new/data这通过管道把一个目录树完整复制到另一个目录保留权限、属主、时间戳而且复制过程中不需要中间文件。相当于用tar流作为文件系统的搬运工源目录一边读目标目录一边写。跟cp相比tar在遇到tar能处理的特殊文件时会透明地保留元数据在内网迁移场景里非常实用。6.3 边打包边加密敏感数据打包之后最好再做个加密。有几种组合方式最简单的是tar输出管道给gpgtar -czvf - /data/secret | gpg -c secret.tar.gz.gpg解包时反向操作gpg -d secret.tar.gz.gpg | tar -xzvf -这样打包、压缩、加密一步到位整个过程不落盘明文。gpg -c用对称加密会提示输入密码适合单机备份。如果想要非对称加密也可以调整gpg的收件人参数思路完全一样。这套组合技在传输敏感文件时能让队友惊叹你竟然还会这招。6.4 与find配合做定期清理备份目录会越积越大光备份不清理等于慢性自杀。一个很成熟的惯例是查找超过7天的备份文件并删除同时配合定时任务。比如find /backup -name *.tar.gz -mtime 7 -delete这里的-delete直接删文件慎用。更稳的写法是先用-print看看列表确认无误再换成-delete。实际生产环境里我通常会把这句话放在独立脚本里并额外限制删除范围避免手滑删掉不该删的东西。6.5 归档超大文件时观察进度用-v会刷屏一样地把每个文件名打印出来但如果文件特别巨大比如几百GB的单个文件你其实看不到太多有效信息。这时候可以不用-v直接看文件大小增长ls -lh backup.tar.gz或者用更高级的方式配合pv命令监控流量tar -czvf - /data/ | pv -s $(du -sb /data/ | awk {print $1}) backup.tar.gzpv会显示传输速度、剩余时间、进度条。-s参数指定总字节数从du -sb拿目录大小。这种方式在备份几十GB的目录时体验极好你至少知道进度在哪而不必盲目猜测命令什么时候能结束。7. 一些我个人的使用心得tar这个命令用熟了以后你会慢慢体会到它在Unix工具箱里的分量。它不复杂参数就那几个但它像万金油一样能跟几乎任何工具组合形成强大的数据流处理链。很多看起来需要专门软件才能做到的事一个tar管道就搞定了。我个人有两点建议。第一常用命令里的参数不要死记硬背先弄清楚-c、-x、-t、-f、-z这五个字母的关系其余的都是组合变化。第二养成相对路径打包的习惯减少解压时踩路径的坑。最后不管用tar做了什么操作尽量在脚本里加上退出码判断因为tar静默失败的场景虽然少但一旦发生影响的可能就是整个备份链路。