Reputation: 140718
Suppose a shell script with the general form
(
# ... lots of code here
) > logfile 2>&1
There is a feature request to optionally have the logs dumped to the terminal as well as the file, which would be written
(
# ... lots of code here
) 2>&1 | tee logfile
The question is, how do I switch between these two pipeline constructs based on the value of a shell variable? Ideally without requiring a cat
process, or anything like that, in the case where the logs are not going to the terminal, for efficiency.
It is a hard requirement to use POSIX shell features only. Also, due to bugs in older versions of zsh, the code inside the parentheses cannot be moved into a shell function.
Upvotes: 1
Views: 45
Reputation: 6058
Using cat
shouldn't be a problem, but if it is:
switcher.sh
:
#!/bin/sh
if $TERMINAL; then
OUTFILE=/dev/tty
else
OUTFILE=/dev/null
fi
(
echo hello
) | tee logfile > $OUTFILE
echo "## log file ##"
cat logfile
$ TERMINAL=false ./switcher.sh
## log file ##
hello
$ TERMINAL=true ./switcher.sh
hello
## log file ##
hello
The implementation of tee
and /dev/null
is such that there won't be extra buffer copies.
Upvotes: 0
Reputation: 72687
My take would be
(
# ... lots of code here
) 2>&1 |
if test "$want_terminal_output" = yes; then
tee logfile
else
cat > logfile
fi
Yes, there's a (useful!) cat
. Is efficiency of a single program really critical? I can see why anyone would consider it unaesthetic. If it hurts your eyes, write a read/write loop in the shell and profile it. Of course you can always duplicate lots of code
and avoid the cat
with the cut-n-paste way of programming so popular in this day and age :-)
Upvotes: 2