I couldn't get Dennis' very simple one-liner to work, so here's a far more convoluted method. I'd try his first.
As mentioned, you can use exec to redirect standard error & standard out for the entire script. Like so:
exec > $LOGFILE 2>&1
This will output all stderr and stdout to $LOGFILE.
Now, since you want to have this displayed to the console as well as a logfile, you're also going to have to use a named pipe for exec to write to, and tee to read from.
(Dennis' one-liner technically does this as well, although obviously in a different way) The pipe itself is created with mkfifo $PIPEFILE
. Then do the following.
# Start tee writing to a logfile, but pulling its input from our named pipe.
tee $LOGFILE < $PIPEFILE &
# capture tee's process ID for the wait command.
TEEPID=$!
# redirect the rest of the stderr and stdout to our named pipe.
exec > $PIPEFILE 2>&1
echo "Make your commands here"
echo "All their standard out will get teed."
echo "So will their standard error" >&2
# close the stderr and stdout file descriptors.
exec 1>&- 2>&-
# Wait for tee to finish since now that other end of the pipe has closed.
wait $TEEPID
If you want to be thorough, you can create and destroy the named pipe file at the start and end of your script.
For the record, I gleaned most of this from a random guy's very informative blog post: (Archived version)