如何在 tar 时重定向 xz 的正常标准输出 | xz?
How to redirect xz's normal stdout when do 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 的日志输出(即非存档输出)捕获到一个日志文件中。在上面的示例中,注销总是由那些 -v
选项生成。
使用上面的命令行,日志输出现在打印在我的终端上。
所以,问题是当你像上面那样使用管道连接tar和xz时,你不能用类似
的东西结束命令行
>Log_File 2>&1
因为之前那个
> OUTPUT_FILE.tar.xz
有解决办法吗?
我试过像这样包装在子外壳中
(tar -cvf - paths_to_archive | xz -1 -T0 -v > OUTPUT_FILE.tar.xz) >Log_File 2>&1
但这没有用。
第一个-cvf -
可以换成cv
.
但是 tar cvf -
的正常标准输出是 tar 文件,它通过管道传输到 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
更能显示管道的进度。它会以百分比的形式告诉您预计到达时间的进度:
size=$(du -bc path1 path2 | tail -1 | awk '{print}')
tar c paths 2> LOG.stderr | pv -s$size | xz -1 -T0 > OUTPUT.tar.xz
tar
的标准输出是压缩包,xz
的标准输出是压缩文件。 None 这些东西是您应该要捕获的日志。 除输出文件本身之外的所有 日志记录都专门写入两个进程的 stderr。
因此,您只需要重定向 stderr,并且 绝不能 重定向 stdout,除非您希望输出文件与日志记录混淆。
{ tar -cvf - paths_to_archive | xz -1 -T0 -v > OUTPUT_FILE.tar.xz; } 2>Log_File
顺便说一句——如果您对 xz -v
输出到 TTY 时打印更多内容感到好奇,答案是 in this line of message.c
:progress_automatic
标志(告诉 xz 设置一个定时器来触发 SIGALRM
——它认为这是应该打印状态的指示——每秒)仅在 isatty(STDERR_FILENO)
为真时设置。因此,在 stderr 被重定向到一个文件后,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
执行所需时间四舍五入到最接近的秒数的代码是可能的,但作为练习留给 reader)。
我需要使用像 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 的日志输出(即非存档输出)捕获到一个日志文件中。在上面的示例中,注销总是由那些 -v
选项生成。
使用上面的命令行,日志输出现在打印在我的终端上。
所以,问题是当你像上面那样使用管道连接tar和xz时,你不能用类似
的东西结束命令行>Log_File 2>&1
因为之前那个
> OUTPUT_FILE.tar.xz
有解决办法吗?
我试过像这样包装在子外壳中
(tar -cvf - paths_to_archive | xz -1 -T0 -v > OUTPUT_FILE.tar.xz) >Log_File 2>&1
但这没有用。
第一个-cvf -
可以换成cv
.
但是 tar cvf -
的正常标准输出是 tar 文件,它通过管道传输到 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
更能显示管道的进度。它会以百分比的形式告诉您预计到达时间的进度:
size=$(du -bc path1 path2 | tail -1 | awk '{print}')
tar c paths 2> LOG.stderr | pv -s$size | xz -1 -T0 > OUTPUT.tar.xz
tar
的标准输出是压缩包,xz
的标准输出是压缩文件。 None 这些东西是您应该要捕获的日志。 除输出文件本身之外的所有 日志记录都专门写入两个进程的 stderr。
因此,您只需要重定向 stderr,并且 绝不能 重定向 stdout,除非您希望输出文件与日志记录混淆。
{ tar -cvf - paths_to_archive | xz -1 -T0 -v > OUTPUT_FILE.tar.xz; } 2>Log_File
顺便说一句——如果您对 xz -v
输出到 TTY 时打印更多内容感到好奇,答案是 in this line of message.c
:progress_automatic
标志(告诉 xz 设置一个定时器来触发 SIGALRM
——它认为这是应该打印状态的指示——每秒)仅在 isatty(STDERR_FILENO)
为真时设置。因此,在 stderr 被重定向到一个文件后,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
执行所需时间四舍五入到最接近的秒数的代码是可能的,但作为练习留给 reader)。