Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

2>&1 6

Status
Not open for further replies.

pauljt

Technical User
Feb 26, 2003
31
0
0
GB
I have seen a number of scripts which have the following
at the end of the command line.

I understand the & is 'background mode' but I am
unsure about the other parts of 2>& 1.

Can anyone clear this up?

Thanks
 
[tt]2>&1[/tt] actually doesn't have anything to do with the background mode. What it means is that your shell should send the output sent to file descriptor 2 ([tt]stderr[/tt], where you print error messages) should instead be redirected ([tt]>[/tt]) to a file descriptor ([tt]&[/tt]) which in this case is 1 ([tt]stdout[/tt], the "normal" place to output to). //Daniel
 

Any process on UNIX can write its output to standard out, standard error or a file. All of these are handled by unix in the same way, so 'stdout' and 'stderr' are considered files. Every file on UNIX is written to using a 'file handle', also known as a 'file descriptor'. This tells the Operating System where the file is and other useful information.

For all processes, stdout has a file descriptor of '1' and stderr has a file descriptor of '2'. These reserved file desciptors are usually associated with the current terminal (or screen) of a process. So if you type 'ls' in an xterm, the output from the 'ls' process is sent to file descriptor '1' which is associated with your xterm.

%ls file*
file1 file2 file3


Equally, if 'ls' encounters any errors, the error text is sent to file descriptor '2', which is also linked with your xterm, so it appears in the same place.

%ls files*
files*: No such file or directory

However, if you wanted to put your information onto a pipe, such as:

ls file* | grep 2
file2

Then you have to remember that the only information that is passed along the pipe, in this case to the 'grep' process, is stdout, or file descriptor '1'. If you mis-typed the command as in the example above, then your error information would not be passed to the grep:

ls files* | grep 2
files*: No such file or directory

There are some cases when you WANT to be able to pass the error information on, for example you may be grep'ing for error messages.

In this case, you need to bind the output sent to stderr onto the same address as stdout. This is what the statement 2>&1 is doing. You might read the statement as:

"stderr (2) is bound (>) onto the address (&) of stdout (1)"

...and it can be used in the form:

command > file 2>&1

(notice that the bind is applied at the end of the line because it affects the whole preceeding process)

This example only works for bourne shell based shells, such as sh, bash and ksh. For csh, you need the more terse syntax:

command >& file

If you want to know more about redirection of file descriptors, you could try the man pages for the shell you are using, and also take a look at the man page for the exec command which gives you the ability to save and restore modified file descriptors.

Christian
 
In Korn and Bourne shell you can redirect stdout and stderr to different files, using command > stdoutfile 2> stderrfile, for example. How do you do this in C shell? Annihilannic.
 
In csh, you can do the following:

(command > stdoutfile) >& stderrfile

This syntax is one of the many reasons I no longer use csh :)


 
Some other cool Korn shell tricks...

You can print to any file by number. That is, if you want to use the print command to send output to stdout or stderr specifically, you can use...
[tt]
print -u1 "This goes to stdout"
print -u2 "This goes to stderr"
[/tt]
So why is this a big deal when you can just use "2>>" to send something to stderr? Because you can create your own file handles! You can do the following...
[tt]
exec 3> ~/my.log

print -u3 "This goes into my own log file my.log"
[/tt]
You can even redirect stdout and stderr to the same place so you don't have to use the "2>&1" construct...
[tt]
exec 1> ~/my.log
exec 2>&1
[/tt]
After these two commands, anything printed or displayed by the script, to either stdout or stderr, will go to the log file. You don't have to redirect anything in the script because once these commands are issued, everything goes to the same file. This is a good thing to put into cron jobs, so you don't have to redirect output in the crontab entry for it.

If you need to undo these redirections in a script, you can do the following...
[tt]
# script is normal at this point

# Save stdout and sdterr
exec 3>&1
exec 4>&2

# Redirect all output to log file
exec 1> ~/my.log
exec 2>&1

# at this point, all output goes to ~/my.log

print "This goes into the log file"

exec 5> ~/another.file
print -u5 "This goes into another.file"

# Then we can restore stdout and stderr
exec 1>&3
exec 2>&4

print "This goes to stdout!"
[/tt]
Hope this helps.

 
You can also create file descriptors to read from...
[tt]
exec 6< some.file
read -u6 RECORD
print &quot;First line of some.file: ${RECORD}&quot;
[/tt]
Too cool!

 

most commonly this is used so that all output is sent to the null device and not shown on the screen. this is handy for things like loginscripts where you dont want users seeing error messages even if a command fails.

so
/sbin/umount /usr >/dev/null 2>&1

does not pop or any info onto the screen as normal and error messages are sent to the null device (the black hole used to send things you dont want to go anywhere).

################
All life is Kaos
################
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top