Home » Questions » Computers [ Ask a new question ]

Force bash script to use tee without piping from the command line

Force bash script to use tee without piping from the command line

I have a bash script with lots of output and I would like to change that script (not create a new one) to copy all the output to a file, just like it would happen if I were piping it through tee.

Asked by: Guest | Views: 39
Total answers/comments: 4
Guest [Entry]

"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)"
Guest [Entry]

"This is combined version of answer posted by Dennis Williamson earlier. Appends both err & std out to script.log in right order.

Add this line to the beginning of your script:

exec > >(tee -a script.log) 2>&1

Note the space between the > signs.
Works for me on GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)"
Guest [Entry]

"You'd just use this:

script logfile.txt
your script or command here

This outputs everything to that log, everything, as well as displaying it on screen. If you want the FULL output, this is how to do it.

And you can then replay the script if you are lazy."
Guest [Entry]

"#!/bin/bash
init
do_something_that_outputs_stuff_to_STDOUT > script.log 2>&1
launch_applications_that_output_to_STDOUT >> script.log 2>&1
fini

You can see more about how it works here:
http://www.xaprb.com/blog/2006/06/06/what-does-devnull-21-mean/"