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
,zsh
或bash
:
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功能,从而zsh
在tee
内部实现一种将相同输出重定向到多个文件(这里是原始 stdout ( >&1
) 和管道以gzip
再次使用进程替换)。
logger
的标准输出实际上将是管道的写入端。在管道的另一端是一个 shell 进程,它读取它并像tee
这样分发它的两个输出。