views:

3268

answers:

4

Is it possible to redirect all of the output of a Bourne shell script to somewhere, but with shell commands inside the script itself?

Redirecting the output of a single command is easy, but I want something more like this:

#!/bin/sh
if [ ! -t 0 ]; then
    # redirect all of my output to a file here
fi

# rest of script...

Meaning: if the script is run non-interactively (for example, cron), save off the output of everything to a file. If run interactively from a shell, let the output go to stdout as usual.

I want to do this for a script normally run by the FreeBSD periodic utility. It's part of the daily run, which I don't normally care to see every day in email, so I don't have it sent. However, if something inside this one particular script fails, that's important to me and I'd like to be able to capture and email the output of this one part of the daily jobs.

Update: Joshua's answer is spot-on, but I also wanted to save and restore stdout and stderr around the entire script, which is done like this:

# save stdout and stderr to file descriptors 3 and 4, then redirect them to "foo"
exec 3>&1 4>&2 >foo 2>&1

# ...

# restore stdout and stderr
exec 1>&3 2>&4
+9  A: 
exec > file
Joshua
Chris Jester-Young
+1  A: 

See here for all the goodness: http://tldp.org/LDP/abs/html/io-redirection.html

Basically what was said by Joshua.

exec > file redirects stdout to a specific file, exec < file replaces stdin by file, etc.

Its the same as usual but using exec (see man exec for more details).

Loki
+1  A: 
dbguy
+1  A: 

Addressing the question as updated.

#...part of script without redirection...

{
    #...part of script with redirection...
} > file1 2>file2 # ...and others as appropriate...

#...residue of script without redirection...

The braces '{ ... }' provide a unit of I/O redirection. The braces must appear where a command could appear - simplistically, at the start of a line or after a semi-colon. (Yes, that can be made more precise; if you want to quibble, let me know.)

You are right that you can preserve the original stdout and stderr with the redirections you showed, but it is usually simpler for the people who have to maintain the script later to understand what's going on if you scope the redirected code as shown above.

Jonathan Leffler
This is much clearer than saving the original descriptors and restoring them later.
Steve Madsen