Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am porting an old ksh script to Bourne shell. The old ksh script contains the following code:

#!/bin/sh

tmpLog=/var/tmp/logfile.$$

exec 1> $tmpLog
exec 2>&1

eval $*
another_command_1
another_command_2

From what I read, it seems that these two exec statements are intended to execute $*, another_command_1, another_command_2 and all following commands; and then redirect all STDERR and STDOUT from those commands into /var/tmp/logfile.$$. However, when I run this in a script the script fails after exec 2>&1.

stefanl@host:~ $ sh -xv ./output.sh echo "Hello"
#!/bin/sh

tmpLog=/var/tmp/logfile.$$
+ tmpLog=/var/tmp/logfile.39918

exec 1> $tmpLog
+ exec
exec 2>&1
+ exec
stefanl@host:~ $

And when I run this on the commandline, my shell freezes after I execute exec 2>&1:

stefanl@host:~ $ tmpLog=/var/tmp/logfile.$$
stefanl@host:~ $ exec 1> $tmpLog
stefanl@host:~ $ exec 2>&1
### FREEZE ###

My questions:

  1. What is exec 2>&1 supposed to do?
  2. Why is it failing for me?
share|improve this question

2 Answers 2

up vote 14 down vote accepted

Your script is not failing - it's working just fine. Your understanding is correct in that exec >logfile; exec 2>&1 redirects both standard output and standard error to logfile. So, you should be looking in the log file and not your terminal for output and error. If you perform those redirections directly in your current shell, it looks like your shell has frozen because you sent all the output away from your terminal.

Note that the output from the xtrace (set -x) option also goes to standard error, which is always file descriptor 2 ... which you sent away to the log file. You should find the rest of it after the exec 2>&1 in there.

share|improve this answer
    
Ah, thanks! And if I open a new window and do a tail -f /var/tmp/logfile.39918 I see everything that I type in the old window. Clever trick! –  Stefan Lasiewski Jul 31 '12 at 19:35
1  
"... sends both standard output and standard input to logfile, ..." should be "standard output and standard error". I'll edit to make the correction. –  Kevin Fegan Feb 9 at 14:48

This form of exec (i.e. without a command) is used to redirect all subsequent output from the current shell interpreter.

from bash's built-in help:

$ help exec
exec: exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
    Replace the shell with the given command.

    Execute COMMAND, replacing this shell with the specified program.
    ARGUMENTS become the arguments to COMMAND.  If COMMAND is not specified,
    any redirections take effect in the current shell.
    [...]

I use exec &> logfile to redirect stdout and stderr at the same time. e.g. most of my backup and rsync wrapper scripts (or any script that produces lots of output that I might want to examine in detail later) start with something like this:

BNAME=$(basename "$0" .sh)
LOGFILE="/tmp/$BNAME.log"
savelog "$LOGFILE"
exec &> "$LOGFILE"

I then run the script from cron, or in the background and use tail -F to watch the logfile as the script is running. The savelog lets me keep the output from the last 7 runs (7 by default, savelog -c can be used to change that).

share|improve this answer
    
The question specifically targets the Bourne shell. Bourne doesn't have the &> operator, nor is quoting the bash man page terribly helpful. The part about cron is irrelevant. –  jw013 Jul 31 '12 at 23:23
    
It still clearly answered his first question 'What is exec 2>&1 supposed to do?` which hadn't actually been answered yet. Assuming a reasonable ability to understand, generalise and extrapolate doesn't deserve a -1. I tend to prefer providing a general explanation instead of just cargo-cult magic to a specific question. BTW, it was the bash help, not the bash man page...it just happened to be the most convenient and succinct documentation to hand, and the relevant point about taking effect in the current shell applies to all versions of sh. –  cas Jul 31 '12 at 23:33
    
I don't see any part in your answer that specifically explains what exec 2>&1 does? I generally downvote answers that encourage misconceptions, whether explicitly or implicitly (in your case, implying sh = bash), because not every person who reads your answer in the future will know the difference. bash is based on sh but in practice there are many differences (like the &>: putting that in a Bourne shell script will probably break it). Also, none of those options that bash exec accepts are likely to be valid. –  jw013 Aug 1 '12 at 14:28
    
My first sentence explains it. As does the final sentence in the bash help output. The remainder is an example of why and how such a feature could be used - why and how typically being omitted from man pages and other reference material. –  cas Aug 1 '12 at 22:24
1  
Q. "What is exec 2>&1 supposed to do?". A. "This form of exec (i.e. without a command) is used to [...]". There is no confusion between bash and sh in that sentence. It is true for all variants of sh. You ignored his first question and answered his second, I ignored his second and answered his first. You're judging my answer by the question you answered, not by the one I answered. –  cas Aug 1 '12 at 23:13

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.