views:

153

answers:

4

I know how to redirect stdout to a file:

exec > foo.log
echo test

this will put the 'test' into the foo.log file.

Now I want to redirect the output into the log file AND keep it on stdout

i.e. it can be done trivially from outside the script:

script | tee foo.log

but I want to do it from the inside

I tried

exec | tee foo.log

but it didn't work

A: 

Neither of these is a perfect solution, but here are a couple things you could try:

exec >foo.log
tail -f foo.log &
# rest of your script

or

PIPE=tmp.fifo
mkfifo $PIPE
exec >$PIPE
tee foo.log <$PIPE &
# rest of your script
rm $PIPE

The second one would leave a pipe file sitting around if something goes wrong with your script, which may or may not be a problem (i.e. maybe you could rm it in the parent shell afterwards).

David Zaslavsky
Vitaly Kushner
@Vitaly: oops, forgot to background `tee` - I've edited. As I said, neither is a perfect solution, but the background processes will get killed when their parent shell terminates, so you don't have to worry about them hogging resources forever.
David Zaslavsky
Yikes: these look appealing, but the output of tail -f is also going to foo.log. You can fix that by running tail -f before the exec, but the tail is still left running after the parent terminates. You need to explicitly kill it, probably in a trap 0.
William Pursell
+1  A: 

Inside your script file, put all of the commands within parentheses, like this:

(
echo start
ls -l
echo end
) | tee foo.log
WReach
pedantically, could also use braces (`{}`)
glenn jackman
well yeah, I considered that, but this is not redirection of the current shell stdout, its kind of a cheat, you actually running a subshell and doing a regular piper redirection on it. works thought. I'm split with this and the "tail -f foo.log )
Vitaly Kushner
+1  A: 

Bash 4 has a coproc command which establishes a named pipe to a command and allows you to communicate through it.

Dennis Williamson
+2  A: 
#!/bin/bash

exec > >(tee logfile.txt)

# uncomment this if you want to also capture stderr - STRONGLY
# recommended, or your logfile will not list any errors.
#exec 2>&1

echo "foo"
echo "bar" >&2
DevSolar
yes yes yes yes! This is *exactly* what I was looking for! Thanks!!!
Vitaly Kushner