有几个 z 实用程序(zless
,zcat
),它们能够以透明的方式读取压缩文件的内容。
是否可以附加到压缩日志文件(任意格式,不一定是 gzip)?
我想要类似以下的东西(ztee
具有感兴趣的功能的虚构实用程序):
echo "[ $( date ) ] message" | ztee -a file.log.gz
答案1
是的,但是没用。
gzip
一些压缩文件格式(包括、bzip2
和使用的格式xz
)做原生支持串联。(它可能使用低级 API 时需要明确选择加入,但命令行解压器默认接受它。)
echo "test 1" | gzip >> log.txt.gz
echo "test 2" | gzip >> log.txt.gz
echo "test 3" | tee >(gzip >> log.txt.gz)
echo "test 4" | (tee /dev/fd/3 | gzip >> log.txt.gz) 3>&1
zcat log.txt.gz
(请注意,egzcat
实际上只是一个 shellscript 包装器gunzip
...)
然而,这意味着每条日志消息都是单独压缩的,而不考虑所有先前的内容。因此,如果你尝试链接许多短日志消息,你的压缩率将非常低,非常很差。(在我以这种方式压缩随机日志文件的测试中,生成的文件实际上成长到其原始大小的 120%,因为所有重复的“标题”开销。)
$ dmesg > test.log
$ cat test.log | gzip > test-single.log.gz
$ cat test.log | while read -r line; do
echo "$line" | gzip
done > test-concat.log.gz
$ du -h test*
500K test-concat.log.gz
416K test.log
64K test-single.log.gz
据我所知,没有工具支持加载现有压缩文件的标头并使用它来压缩新数据。要实现这一点,您需要运行一个持久gzip
进程并定期通过 stdin 向其提供日志。例如:
#!/bin/bash
# open a subprocess (the bash equivalent of 'popen')
coproc LOG { gzip >> log.txt.gz; }
echo "doing stuff" >&${LOG[1]}
echo "doing more stuff" >&${LOG[1]}
echo "still doing stuff" >&${LOG[1]}
# close its stdin to finish compression
exec {LOG[1]}>&-
在“标准” shell 中,你可以使用命名管道实现相同的功能,或者更简单地重定向整个剧本到gzip
。 (只需将同一条消息打印一次到 stdout,一次到 stderr,您就得到了tee
。)
有关压缩流连接的更多信息:
https://stackoverflow.com/questions/8005114/fast-concatenation-of-multiple-gzip-files
https://www.gnu.org/software/gzip/manual/html_node/Advanced-usage.html
可以将多个压缩文件连接起来。在这种情况下,gunzip 将一次性提取所有成员。如果一个成员损坏,在删除损坏的成员后,其他成员可能仍可恢复
https://tukaani.org/xz/format.html
连接:与 .gz 和 .bz2 文件一样,可以按原样连接 .xz 文件。解压器可以像解压常规单流 .xz 文件一样解压连接文件。