0

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

我完全了解以前的问题,例如 在一个命令中创建 tar.xz利用多核进行 tar+gzip/bzip 压缩/解压缩

从他们那里,我发现这个命令行最有效:

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

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

不幸的是,我真的很想将所有 tar 和 xz 的日志输出(即非归档输出)捕获到一个日志文件中。在上面的示例中,注销总是由这些-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

但这没有用。

4

2 回答 2

2

的普通标准输出tar是 tarball,普通标准输出xz是压缩文件。这些都不是您应该要捕获的日志。除输出文件本身之外的所有日志记录都专门写入两个进程的 stderr。

因此,您只需要重定向 stderr,并且不得重定向 stdout,除非您希望输出文件与日志记录混合。

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

顺便说一句——如果你对为什么xz -v在输出到 TTY 时打印更多内容感到好奇,答案就在这一行中message.c:指示应打印状态的指示——每秒)仅在为真时设置。因此,在 stderr 被重定向到文件后,根本不再打印此输出;问题不在于它没有正确重定向,而是它不再存在progress_automaticSIGALRMisatty(STDERR_FILENO)xz

但是,如果您真的愿意,您可以从自己的代码中发送SIGALRM到每一秒:xz

{
  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到最接近的秒数的代码,但留给读者作为练习)。

于 2018-01-25T22:53:14.977 回答
0

首先-cvf -可以替换为cv

但正常的标准输出tar cvf -是通过管道传输到xz. 不知道我是否完全理解,也许是这样:

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
于 2018-01-25T22:37:06.690 回答