如何在tar |中重定向xz的正常标准输出XZ?

时间:2018-01-25 22:11:29

标签: linux bash tar xz

我需要使用像xz这样的压缩器来压缩巨大的tar档案。

我完全了解以前的问题     Create a tar.xz in one command 和     Utilizing multi core for tar+gzip/bzip compression/decompression

从他们那里,我发现这个命令行主要起作用:

tar -cvf - paths_to_archive | xz -1 -T0 -v > OUTPUT_FILE.tar.xz

我使用管道解决方案,因为我绝对必须能够将选项传递给xz。特别是,xz非常占用CPU,所以我必须使用-T0来使用所有可用的内核。这就是为什么我没有使用其他可能性,比如tar的--use-compress-program或-J选项。

不幸的是,我真的想要将所有tar和xz的日志输出(即非归档输出)捕获到日志文件中。在上面的示例中,log outout始终由-v个选项生成。

使用上面的命令行,该日志输出现在打印在我的终端上。

所以,问题是当你使用管道来连接tar和xz时,你不能用

这样的命令行结束命令行
>Log_File  2>&1

因为早先的

> OUTPUT_FILE.tar.xz

有解决方案吗?

我尝试在这样的子shell中包装

(tar -cvf - paths_to_archive | xz -1 -T0 -v > OUTPUT_FILE.tar.xz) >Log_File  2>&1

但这没效果。

2 个答案:

答案 0 :(得分:1)

tar的正常标准输出是tarball,xz的正常标准输出是压缩文件。这些都不是您想要捕获的日志。 除输出文件本身以外的所有日志记录都是专门为stderr写入的。

因此,您只需要重定向stderr,并且一定不能重定向标准输出,除非您希望输出文件与日志记录混在一起。

{ tar -cvf - paths_to_archive | xz -1 -T0 -v > OUTPUT_FILE.tar.xz; } 2>Log_File

顺便说一下 - 如果您对xz -v输出到TTY时打印更多内容的原因感到好奇,答案是in this line of message.cprogress_automatic标记(告诉xz设置一个计时器来触发一个SIGALRM - 它被视为表示应该打印状态 - 每秒一次)仅在isatty(STDERR_FILENO)为真时设置。因此,在将stderr重定向到文件后,xz根本不再打印此输出;问题不在于它没有被正确地重定向,而是不再存在

但是,如果你真的如此倾向,你可以每秒从你自己的代码发送SIGALRMxz

{
  xz -1 -T0 -v > OUTPUT_FILE.tar.xz < <(tar -cvf - paths_to_archive) & xz_pid=$!
  while sleep 1; do
    kill -ALRM "$xz_pid" || break
  done
  wait "$xz_pid"
} 2>Log_File

(避免将xz执行到最近的秒所需的时间四舍五入的代码是可能的,但留给读者的练习。)

答案 1 :(得分:0)

首先-cvf -可以替换为cv

但是tar cvf -的正常stdout输出是通过管道传输到xz的tar文件。不确定我是否完全理解,也许这个:

tar cv paths | xz -1 -T0 > OUTPUT.tar.xz 2> LOG.stderr

tar cv paths 2> LOG.stderr | xz -1 -T0 > OUTPUT.tar.xz

tar cv paths 2> LOG.tar.stderr | xz -1 -T0 > OUTPUT.tar.xz 2> LOG.xz.stderr

不确定-T0是否已实施,您使用的是哪个版本的xz? (可能https://github.com/vasi/pixz值得仔细研究)pv程序在某些系统上与sudo apt-get install pv一起安装,在显示管道进度方面比xz -v更好。它将以ETA的百分比形式告诉您进度:

size=$(du -bc path1 path2 | tail -1 | awk '{print$1}')
tar c paths 2> LOG.stderr | pv -s$size | xz -1 -T0 > OUTPUT.tar.xz