I'm running a propietary program which generates text output. Kind of like a logger.
logger
I'd like to both view this output on the terminal to watch the server breathe, and send it to a text file. So normally I'd do:
logger | tee /tmp/log.txt
But these log files can become large enough to overwhelm my VMs disk space. Instead of sending the text to an uncompressed text file, I'd like it to be compressed immediately. So I might do:
logger
in one terminal and
logger | gzip > /tmp/log.gz
in another terminal. But this doesn't feel very *nixy.
Is there a way I can accomplish this in one command, similar to using tee
? Here is what I'm going for, which obviously won't work, but maybe you'll get the idea:
logger | tee gzip > /tmp/log.txt
Best Answer
With
ksh93
,zsh
orbash
:That uses that
ksh
feature called process substitution.>(gzip > /tmp/log.txt.gz)
is substituted with the path of a file (typically something like/dev/fd/something
, but that could also be a temporary named pipe) that refers to the writing end of a pipe. At the other (reading) end of that pipe, the shell connects the standard input of a new process (run in background) that executes thegzip
command.So, when
tee
writes to that file, it's actually feeding the data togzip
.On systems with
/dev/fd/n
, you can do it manually (with any Bourne-like shell but ksh93) like:(though in that case
/dev/fd/3
refers to the original stdin which we've made available on the file descriptor 3 with3>&1
, not to the pipe togzip
which here is just connected totee
's stdout)With
zsh
:That uses
zsh
multios feature wherebyzsh
implements a sort oftee
internally to redirect the same output to more than one file (here the original stdout (>&1
) and the pipe togzip
using process substitution again.logger
's stdout will actually be the writing end of a pipe. At the other end of the pipe is a shell process that reads it and distributes it both outputs liketee
would.