将标准输入发送到控制台和压缩文件

Joh*_*ing 6 linux shell terminal

我正在运行一个生成文本输出的专有程序。有点像记录器。

logger
Run Code Online (Sandbox Code Playgroud)

我想在终端上查看此输出以观察服务器呼吸,并将其发送到文本文件。所以通常我会这样做:

logger | tee /tmp/log.txt
Run Code Online (Sandbox Code Playgroud)

但是这些日志文件可能会变得足够大,以至于我的 VM 磁盘空间不堪重负。我不想将文本发送到未压缩的文本文件,而是希望它立即被压缩。所以我可能会这样做:

logger
Run Code Online (Sandbox Code Playgroud)

在一个终端和

logger | gzip > /tmp/log.gz
Run Code Online (Sandbox Code Playgroud)

在另一个终端。但这感觉不太*。

有没有一种方法可以在一个命令中完成此操作,类似于使用tee? 这是我要做的,这显然行不通,但也许你会明白:

logger | tee gzip > /tmp/log.txt
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 18

ksh93,zshbash:

logger | tee >(gzip > /tmp/log.txt.gz)
Run Code Online (Sandbox Code Playgroud)

这使用了ksh称为进程替换的功能。>(gzip > /tmp/log.txt.gz)取代的具有一个文件的路径(通常类似于/dev/fd/something,但也可以是一个临时命名管道),其指的是管的书写端。在该管道的另一端(读取),shell 连接执行gzip命令的新进程(在后台运行)的标准输入。

因此,当tee写入该文件时,它实际上是将数据提供给gzip.

在带有 的系统上/dev/fd/n,您可以手动执行(使用任何类似 Bourne 的 shell,但 ksh93),例如:

{ logger | tee -a /dev/fd/3 | gzip > /tmp/log.txt.gz; } 3>&1
Run Code Online (Sandbox Code Playgroud)

(虽然在这种情况下/dev/fd/3是指我们在文件描述符 3 上提供的原始标准输入3>&1,而不是gzip这里只是连接到tee标准输出的管道)

zsh

logger >&1 > >(gzip > /tmp/log.txt.gz)
Run Code Online (Sandbox Code Playgroud)

它使用zsh multios功能,从而zshtee内部实现一种将相同输出重定向到多个文件(这里是原始 stdout ( >&1) 和管道以gzip再次使用进程替换)。

logger的标准输出实际上将是管道的写入端。在管道的另一端是一个 shell 进程,它读取它并像tee这样分发它的两个输出。