Linux tar命令选项顺序不同导致"Exiting with failure status due to previous errors"

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

按照惯例,遇到Linux的问题先说环境:我用的是Centos 7.6。

今天遇到了这样一个问题,改变tar命令的选项顺序后,会报错”Exiting with failure status due to previous errors“,但是还是会创建一个普通格式的压缩文件:

# 假设我们所在的目录下有一个目录叫test,test里面有一个叫test.test的文件
tar -cvfz test.tar.gz test/
# tar: test.tar.gz: Cannot stat: No such file or directory
# test/
# test/test.test
# tar: Exiting with failure status due to previous errors
ls
# ... z ...
# 多了一个叫z的文件
tar -tvf z
# test/
# test/test.test
# 可以看到压缩包内容,成功创建了压缩包
tar -ztvf z
# gzip: stdin: not in gzip format
# 但压缩包不是gzip格式的

一直以来,在Linux中进行压缩,比如用gzip吧,用的命令都是tar -zcvf test.tar.gz test/,也没有深究过为什么要这么用。其实哪怕用man tar查看文档,得到的文档也没有说明选项的顺序会不会对结果有影响。理论上来说,选项顺序对结果是不应该有影响的,但是这个问题就是发生了。

再次进行测试。这次用老式的Unix写法,一切正常:

tar cvfz test.tar.gz test/
# test/
# test/test.test
tar -ztvf test.tar.gz
# test/
# test/test.test

这就很奇怪了。根据上面的现象,可以得出一个猜测:tar命令在选项前有-时,会将选项中f后的第一个“单词”当成生成压缩文件的名字。我们都知道,tar的命令格式是tar [-选项] [目标文件名] [源],也就是说,命令会被分割成tar [-cvf] [z] [test.tar.gz test/],从test.tar.gz和test/中生成一个叫z的普通压缩文件(因为此时z已经被认为是文件名,所以不会调用gzip)。而又因为test.tar.gz是一个不存在的文件,所以会报错文件不存在。

再次调整一下选项顺序,验证一下上面的猜想:

tar -cfvz test.tar.gz test/
# tar: test.tar.gz: Cannot stat: No such file or directory
# test/
# test/test.test
# tar: Exiting with failure status due to previous errors
ls
# ... vz ...
# 多了一个叫vz的文件
tar -tvf vz
# test/
# test/test.test
tar -ztvf vz
# gzip: stdin: not in gzip format
############
tar -fcvz test.tar.gz test/
# tar: You must specify one of one of the '-Acdtrux' or '--test-label' options

看来我们的猜想是正确的,tar命令的执行结果会受到f的位置的影响。我看,Stack Exchange上的老外也说了:

As @jcbermu said, for most programs and in most cases, the order of command line flags is not important. However, some flags expect a value. Specifically, tar’s -f flag is:

-f, --file ARCHIVE
use archive file or device ARCHIVE

So, tar expects -f to have a value and that value will be the name of the tarfile it creates. For example, to add all .jpg files to an archive called foo.tar, you would run
tar -f foo.tar *jpg
What you were running was

tar -cfv test.tar *.jpg

tar understands that as "create (-c) an archive called v (-fv), containing files test.tar and any ending in .jpg.
When you run tar -cvf test.tar *.jpg on the other hand, it takes test.tar as the name of the archive and *jpg as the list of files.

但是为什么呢?猜想总是需要理论支撑的。网上查半天也没查到,文档里也没说,无奈之下只能自己找tar的源码看了(顺便吐槽一下C语言的可读性)。出于简洁(而且也不知道自己的理解对不对),就只放一些主要逻辑好了:

// tar.c
/* Main routine for tar.  */
int main (int argc, char **argv)
{
  /* Decode options.  */
  decode_options (argc, argv);
  /* Main command execution.  */
  switch (subcommand_option)
    {
    case UNKNOWN_SUBCOMMAND:
      USAGE_ERROR ((0, 0,
		    _("You must specify one of the `-Acdtrux' or `--test-label'  options")));

    case CREATE_SUBCOMMAND:
      create_archive ();
      break;
    }
  /* Dispose of allocated memory, and return.  */
  if (exit_status == TAREXIT_FAILURE)
    error (0, 0, _("Exiting with failure status due to previous errors"));
  return exit_status;
}

可以看出,在main函数里调用了decode_options,对命令行输入的参数进行了解析。从输出里可以看出,所有的问题都是因为输入没有被正确解析。那么,所有的问题都在decode_options函数里了。

同时,这一段代码这也能解释,为什么报错但是压缩包还是会被创建,因为代码是按照指令执行的,指令之间其实互不影响;而且,报错退出是在整个main函数的最后,并不影响前面的行为(比如,创建)的执行。

// tar.c
/* Convert old-style tar call by exploding option element and rearranging
     options accordingly.  */
  if (argc > 1 && argv[1][0] != '-')
    {
      int new_argc;		/* argc value for rearranged arguments */
      char **new_argv;		/* argv value for rearranged arguments */
      char *const *in;		/* cursor into original argv */
      char **out;		/* cursor into rearranged argv */
      const char *letter;	/* cursor into old option letters */
      char buffer[3];		/* constructed option buffer */
      /* Initialize a constructed option.  */
      buffer[0] = '-';
      buffer[2] = '\0';
      /* Allocate a new argument array, and copy program name in it.  */
      new_argc = argc - 1 + strlen (argv[1]);
      new_argv = xmalloc ((new_argc + 1) * sizeof (char *));
      in = argv;
      out = new_argv;
      *out++ = *in++;
      /* Copy each old letter option as a separate option, and have the
	 corresponding argument moved next to it.  */
      for (letter = *in++; *letter; letter++)
	{
	  struct argp_option *opt;
          
	  buffer[1] = *letter;
	  *out++ = xstrdup (buffer);
	  opt = find_argp_option (options, *letter);
	  if (opt && opt->arg)
	    {
	      if (in < argv + argc)
		*out++ = *in++;
	      else
		USAGE_ERROR ((0, 0, _("Old option `%c' requires an argument."),
			      *letter));
	    }
	}
      /* Copy all remaining options.  */
      while (in < argv + argc)
	*out++ = *in++;
      *out = 0;
      /* Replace the old option list by the new one.  */
      argc = new_argc;
      argv = new_argv;
    }

这一段代码能解释为什么用老式的Unix实现(也就是不加-)不会受影响。因为对于Unix实现,tar会把选项直接拆成对应的指令,然后执行。比如,cvfz会被直接拆成['c','v','f','z'],并且将参数argc和argc替换掉。

// tar.c
/* Parse all options and non-options as they appear.  */
  prepend_default_options (getenv ("TAR_OPTIONS"), &argc, &argv);
  if (argp_parse (&argp, argc, argv, ARGP_IN_ORDER, &idx, &args))
    exit (TAREXIT_FAILURE);
// prepargs.c
/* Prepend the whitespace-separated options in OPTIONS to the argument
   vector of a main program with argument count *PARGC and argument
   vector *PARGV.  */
void prepend_default_options (char const *options, int *pargc, char ***pargv);

这一段就是对选项进行解析。这个函数的功能已经很明确了,就是提取选项里的命令,并且放到前面。

// tar.c
static error_t parse_opt (int key, char *arg, struct argp_state *state)
{
  struct tar_args *args = state->input;
  switch (key) {
    case ARGP_KEY_ARG:
      /* File name or non-parsed option, because of ARGP_IN_ORDER */
      name_add_name (arg, MAKE_INCL_OPTIONS (args));
      args->input_files = true;
      break;
    case 'c':
      set_subcommand_option (CREATE_SUBCOMMAND);
      break;
    case 'f':
      if (archive_names == allocated_archive_names)
	archive_name_array = x2nrealloc (archive_name_array,
					 &allocated_archive_names,
					 sizeof (archive_name_array[0]));
      archive_name_array[archive_names++] = arg;
      break;
  }
}
// agrp.h
/* This is not an option at all, but rather a command line argument.  If a
   parser receiving this key returns success, the fact is recorded, and the
   ARGP_KEY_NO_ARGS case won't be used.  HOWEVER, if while processing the
   argument, a parser function decrements the NEXT field of the state it's
   passed, the option won't be considered processed; this is to allow you to
   actually modify the argument (perhaps into an option), and have it
   processed again.  */
#define ARGP_KEY_ARG            0
// names.c
/* Add to name_array the file NAME with fnmatch options MATCHING_FLAGS */
void name_add_name (const char *name, int matching_flags)
{
  static int prev_flags = 0; /* FIXME: Or EXCLUDE_ANCHORED? */
  struct name_elt *ep;

  check_name_alloc ();
  ep = &name_array[entries++];
  if (prev_flags != matching_flags)
    {
      ep->type = NELT_FMASK;
      ep->v.matching_flags = matching_flags;
      prev_flags = matching_flags;
      check_name_alloc ();
      ep = &name_array[entries++];
    }
  ep->type = NELT_NAME;
  ep->v.name = name;
  name_count++;
}

答案在此揭晓:在选项里遇到f,就会把arg直接加入archive_names[]里;也就是说,会把选项里剩下的内容当做文件名。事实上,创建压缩文件的时候会把数组里第一个字符串作为目标文件名,可以在create.c里查看。

所以,这算不算tar的一个bug呢?

Linux tar命令实战:从打包压缩到生产环境备份全解析 最近在服务器迁移和项目部署时,经常需要处理大量的日志文件、源码包和配置文件。直接传输零散文件不仅效率低下,还容易出错。这时, tar 命令就成了我们最可靠的“打包工”和“压缩工”。无论是备份关键数据,还是分发程序,掌握 tar 的用法都是 Linux 系统管理和开发运维的必备技能。 本文将从零开始,详细拆解 tar 命令的打包、压缩、解压全流程。我们会先理清“打包”和“压缩”的核心概念,然后通过大量可复制的命令示例,带你一步步掌握各种常用参数和高级用法。最后,还会分享生产环境中备份、增量归档等实战技巧和避坑 阅读详情

相关推荐

Linux tar命令完全指南:从打包压缩原理到运维实战

如果你在Linux服务器上工作,每天都要和文件打交道,那么“打包”和“压缩”这两个词对你来说一定不陌生。你可能经常需要备份日志、分发代码,或者从网上下载一个以 .tar.gz 结尾的软件包。但你是否曾对 tar 命令那一长串参数感到困惑? -zcvf 和 -zxvf 到底有什么区别?为什么有时候解压会报错“gzip: stdin: not in gzip format”?又或者,你明明想压缩,结果却只打了个包,文件大小一点没变? 这些问题背后,其实是对 tar 这个“打包”工具和 gzip 、 bzip2

424

anaconda3报错Exiting with failure status due to previous errors

[/root/anaconda2] &gt;&gt;&gt;  PREFIX=/root/anaconda2 Anaconda2-5.0.0-Linux-ppc64le.sh: line 317: bunzip2: command not found tar: This does not look like a tar archive tar: Exiting with failure statu...

JavaPub 1231

Linux压缩命令深度解析:从tar、gzip到zip的运维实战指南

文件压缩是数据处理与存储中的基础技术,其核心原理在于通过算法消除数据冗余,以更小的体积存储或传输信息。在Linux系统中,这主要涉及归档与压缩两个步骤,其中tar负责将多个文件打包成一个归档文件并保留元数据,而gzip、bzip2、xz等工具则基于不同的压缩算法(如DEFLATE、BWT、LZMA)对归档文件进行压缩,在速度、压缩率和资源消耗上各有权衡。这项技术的工程价值在于显著节省存储空间和网络带宽,是数据备份、软件分发和日志管理的基石。其典型应用场景包括系统运维中的日志打包、跨平台文件交换以及大型资源(

weixin_34204722的博客 358

Linux打包解压文件-Exiting with failure status due to previous errors

Linux下打包和解压文件

软件测试入门&进阶 1136

【Splunk 备份 】如何修复“tarExiting with failure status due to previous errors

如何修复“tarExiting with failure status due to previous errors

shenghuiping2001的专栏 813

压缩文件报错 tar: Exiting with failure status due to previous errors

tar: Exiting with failure status due to previous errors linux tar 压缩文件的时候报错

细雨青峦的博客 2万+

tar: Exiting with failure status due to previous errors

dev/null 是一个特殊的文件,写入到它的内容都会被丢弃(不显示、不打印、不记录);但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。从图上可以看到:tomcat76/work/Catalina/localhsot/manager/org Permission denied(权限被拒绝)原因是打包的文件夹中有超出权限的文件或文件夹,比如你用普通用户登录,但是存在root权限的文件夹。2.找到超出权限的文件或文件夹,更改文件或文件夹权限或者删除该文件或文件夹。

qq_43236333的博客 5554

Linux解压命令全解析:从tar.gz到zip,掌握核心参数与实战技巧

文件压缩与解压是数据处理和系统运维中的基础操作,其核心原理是通过特定算法减少数据存储空间或传输带宽。在Linux/Unix生态中,归档与压缩通常分离,由不同工具协同完成,这体现了模块化设计思想。从技术价值看,高效的压缩解压能力直接影响软件分发效率、备份恢复速度和日志分析流程。常见的应用场景包括源码包部署、日志归档、数据备份及跨平台文件交换。针对不同需求,gzip、bzip2、xz等工具在压缩率、速度和资源消耗上各有侧重,而tar命令的-f、-C、-v等参数则提供了精细控制。本文以tar.gz和zip等主流格

weixin_30552811的博客 365

Linux解压命令全解析:从tar.gz到zip的实战技巧与错误排查

Linux系统管理与软件开发中,文件压缩与解压是基础且高频的操作。压缩技术通过特定算法减少文件体积,便于存储和传输,其原理主要分为无损压缩(如gzip、bzip2)和有损压缩两类。掌握解压命令不仅能提升工作效率,更是理解Linux管道哲学和自动化脚本编写的重要基础。从运维部署到日常开发,正确处理各类压缩包(如.tar.gz、.zip、.tar.xz)是保障工作流顺畅的关键。本文将聚焦实战场景,详解如何应对“invalid zip archive: could not find eocd”等常见错误,并提供

weixin_34280237的博客 403

Linux tar命令深度解析:从czvf/xzvf到运维实战与性能优化

Linux系统管理与数据处理中,文件归档与压缩是基础且核心的操作。其原理在于将多个文件及目录的元数据(如权限、时间戳)聚合为一个单一文件,再通过压缩算法减少存储与传输开销。这项技术的价值在于保障数据完整性、提升备份与迁移效率,并广泛应用于软件分发、日志归档和系统备份等场景。本文聚焦于Linux环境下经典的tar命令,深入剖析其czvf(创建归档)与xzvf(解压归档)参数组合的工作机制,并结合实际运维案例,探讨如何应对权限问题、路径管理及增量备份等挑战,旨在帮助读者从“会用”进阶到“懂原理、能排错、善优化

weixin_30552811的博客 393

Linux cp/mv/tar命令深层原理与生产避坑指南

Linux文件操作命令(如cp、mv、tar)并非简单工具,而是对文件系统语义层的直接操控接口。理解其底层原理——包括inode管理、目录项原子性、POSIX归档协议及元数据保留机制——是避免生产事故的关键。例如,cp -a 实质是批量保全权限、SELinux上下文与扩展属性;mv 跨文件系统时退化为复制+删除,丧失原子性;tar 的 --newer-mtime 与 reflink 支持则分别体现时间戳语义和写时复制能力。这些特性共同构成Linux运维的可靠性基石,广泛应用于日志归档、配置热更、增量备份与容

weixin_30435261的博客 392

Linux tar命令深度解析:从czvf/xzvf到高级备份与性能优化

Linux系统管理与运维中,文件归档与压缩是基础且高频的操作需求。归档工具通过将多个文件集合为单一包体,保持目录结构与元数据完整性;压缩技术则基于算法减少数据体积,提升存储与传输效率。这种技术组合在数据备份、软件分发和系统迁移等场景中具有核心价值。tar命令作为Unix哲学的经典体现,通过管道机制无缝集成gzip、bzip2、xz等压缩算法,形成了czvf(创建gzip压缩包)和xzvf(解压gzip包)等高效指令范式。本文聚焦于路径安全处理、增量备份实战与多算法性能对比,结合gzip压缩与xz压缩等热词

weixin_33894640的博客 338

Linux打包与压缩核心指南:从tar、gzip到xz的实战详解

Linux系统管理与文件处理中,打包与压缩是两项基础且核心的操作。打包(Archiving)的本质是将多个文件及元数据聚合为单一文件流,而压缩(Compression)则是通过算法消除数据冗余以减小体积。理解这一原理对于高效管理文件、节省存储空间和加速网络传输至关重要。在技术实现上,Linux提供了以tar为代表的归档工具,以及gzip、bzip2、xz等压缩算法,它们通过管道组合,形成了如.tar.gz这样的经典格式。这些工具在软件分发、日志轮转、系统备份等工程实践中广泛应用。例如,结合tar命令与gz

weixin_34226706的博客 346

Linux tar命令深度解析:从归档原理到生产级备份实战

如果你在 Linux 服务器上工作,一定遇到过这样的场景:需要把整个项目目录发给同事,或者把日志文件备份到远程存储。直接传一堆零散文件?效率太低,还容易漏。这时候,你第一个想到的命令,很可能就是 tar 。 但 tar 真的只是“打包压缩”那么简单吗?为什么同样是打包,有人用 tar -czvf ,有人用 tar -xJf ,背后的 z 、 J 、 j 到底有什么区别?更关键的是,当你在生产环境执行 tar -czf backup.tar.gz /var/log 时,是否意识到这个命令可能隐藏着“吞噬整个根

weixin_30634661的博客 352

Linux tar命令深度解析:从打包压缩到增量备份实战

这次我们来看一个 Linux 系统管理员和开发者必须掌握的核心工具: tar 命令。它远不止是“打包压缩”那么简单,而是文件归档、备份、迁移和分发的基石。无论你是要备份网站目录、分发软件源码,还是将日志文件归档到远程服务器, tar 都是绕不开的一环。 很多人对 tar 的印象停留在 tar -czvf 和 tar -xzvf ,但它的能力远不止于此。本文将深入拆解 tar 命令,从最基础的打包解包,到高级的增量备份、排除特定文件、保留文件属性,再到与压缩工具(gzip, bzip2, xz)的高效协作。我

chuliaoqiao4046的博客 379

CentOS 7系统级备份与还原实战:基于Tar的全量/增量策略与避坑指南

Linux系统运维中,数据备份与恢复是保障业务连续性的核心技术。其核心原理在于通过捕获文件系统的完整状态(包括权限、属性和时间戳),创建可恢复的镜像。这项技术的核心价值在于实现灾难恢复、系统迁移和配置回滚,广泛应用于服务器维护、数据中心迁移和开发环境管理。通过合理运用全量、增量与差异备份策略,结合自动化工具,可以在最小化存储开销的同时确保数据安全。本文聚焦于在CentOS 7环境中,使用经典的Tar命令实现高效可靠的系统级备份与还原,并深入探讨了UEFI/GPT引导、SELinux上下文等常见疑难问题的解

weixin_30918633的博客 356

安装完成Ubuntu20.04之后要做的事:基础配置、界面美化、异常处理、常用软件的安装与常用命令

换源、安裝显卡驱动、设置新建文件模板、卸载系统软件、安裝中文输入法、双系统时间同步、修改双系统启动顺序以及美化grub界面、自动挂载Windows盘、设置录屏时间无限制、系统卡死的处理办法、主题美化、安装Chrome浏览器并加入apt更新、安裝VScode、WPS、PDF阅读器Foxit Reader、安裝与卸载微信QQ、安裝视频播放器smplayer,系统备份与恢复

zardforever123的博客 3万+

Linux文件权限原理与实战:从inode校验到生产排障

Linux文件权限是操作系统访问控制的基础机制,其核心在于内核对inode中mode_t字段的原子化校验,结合UID/GID所有权模型实现自主访问控制(DAC)。该机制决定了进程能否读写文件、执行程序或遍历目录,直接影响Web服务部署、Docker容器挂载、Git协作及安全加固等关键场景。理解chmod、chown、umask等命令背后的权限计算逻辑(如八进制映射、符号模式增量修改、umask按位取反),能避免777滥用、403错误、Operation not permitted等高频故障。本文深入inod

weixin_33701294的博客 429

Nginx架构及配置详解

概述 Nginx采用C进行编写,是俄罗斯程序员开发的一款轻量级的可构建Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器的软件, Nginx服务器是一个高性能的HTTP和反向代理web服务器,同时也可提供了IMAP/POP3/SMTP服务。nginx常用作跑静态和做负载反向代理,动态php交给apache处理,因后者比较稳定,jsp交给tomcat、resin或jboss。n......

企业实战系列集 ●●● https://ximenjianxue.blog.csdn.net 6978
上一篇: Shell test字符串比较恒为真的bug
下一篇: Vue 3.0 function-based API尝鲜(二):配置与启动
元无心
博客等级 码龄8年 146粉丝 191原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值