Tuesday, August 31, 2010

Unix File Descriptors



 Unix has 3  file descriptors:
  • 0 - Input
  • 1 - Output
  • 2 - Error
Every file descriptor is associated with a value. The above list shows the 3 file descriptors and their associated value. Before we see too much into this, let us go straight to see some examples.

Output File Descriptor:
#cat f1
I am an Indian,
And I love Unix.
#
 In the above example, the cat command displayed the contents of the file f1. The output of the cat command got displayed or got re-directed to the terminal which is the output file descriptor by default. To prove it, lets try this:

#tty
/dev/pts/1
#cat f1 > /dev/pts/1
I am an Indian,
And I love Unix.
#
  tty command gives the terminal info. As shown above, when we specify the /dev/pts/1 as the output file, the contents still got displayed in the terminal. The output of a command can be re-directed to a file or a terminal using the re-direction operator(>). Also, note the value of the output file descriptor "1" is not specified above . It is so because the symbol ">" defaults to output.
#cat f1 1> /dev/pts/1
I am an Indian,
And I love Unix.
#
   In this case, the output file descriptor is specified explicitly to redirect the output to a terminal.

Note: There should be no space between 1 and > symbol. If a space is provided, the cat command treats 1 as a filename.

Similarly, to re-direct the output of a command to another file:
#cat f1  1> f2
# cat f2
I am an Indian,
And I love Unix.
#
Or more simply:
#cat f1  > f2
# cat f2
I am an Indian,
And I love Unix.
# 
Error File Descriptor:
1. Let us try to print the contents of a non-existent file:
#cat abc
cat: abc: No such file or directory. 
  The above shown output is an error message of the cat command. Please note that the error message also got re-directed to the terminal which means the terminal is the default file descriptor for the errors.

2.  Let us try to re-direct this error message to a file as in the case of output re-direction:
#cat abc >f2
cat: abc: No such file or directory. 
# cat f2
#
  What happened. The error message did not get re-directed to the file f2. As we said earlier, when we use ">", only the output gets re-directed.

3.
#cat abc 2> /dev/null
#
   In the above example, no error message is displayed on the terminal because the errors are now redirected to a null terminal.

4. One of the common instances where we dont intend to use error messages is during the find command. When find searches in directories where the user does not have the read permissions, it throws error. To redirect those errors:
#find . -mtime -10   2>/dev/null
5. However, there are instances when the error messages are required for later analysis. For example, you are running a script where-in you want to capture all the error messages(assuming StartScript.sh is the name of the script):
#./StartScript.sh  2> temp
6. In cases, certain scripts might run for hours and hence the user cannot be present in front of the terminal all the time. In such cases, the user can re-direct both the output and error to some files which he/she can analyze later:
#./StartScript.sh >f1 2>f2
  The above command re-directs the output to a file f1, and the error to a file f2.

7. If the user wants to re-direct both the output and error to the same file:
#./StartScript.sh >f1 2>&1
 Two things to be noted in the above example:
  •  First, the output got re-directed to the file f1
  • 2>&1 - This means re-direct the error(2) to the same terminal as the output(&1). Since output is re-directed to f1, the error is also redirected to f1.
8. However, if you change the above command like:
#./StartScript.sh 2>&1 >f1
   This will not work. Its because
  • First, the error got re-directed to the same place as the output. Since the output re-direction is not defined yet, the error gets re-directed to its default terminal itself.
  • Secondly, the output is now re-directed to the file f1. 
  So, on running the above command, all the output gets re-directed to the output file f1, and the errors are captured in the terminal itself.

Let's take a more simpler example to clarify the above point. Lets take two files, f1 which is a valid file, and f0 which is an invalid file.
#cat f1 f0 2>&1 >f2
cat: f0: No such file or directory
#cat f2
I am an Indian,
And I love Unix.
# 
Input  File Descriptor:
 Now, lets come to our last part: input descriptor. Like output and error, the terminal is the default input descriptor.
#read x
20
#echo $x
20
#
  The read command expects input from the user. When the read command is typed in, it prompts the user for an input.  And the input is provided in the terminal which in turn is saved in the variable x in this case.

The input can also come from a file:
#cat f1
20
#read x < f1
#echo $x
20
#
  • The file f1 contained the value 20
  • The read command is made to take the input from file f1. Note the symbol "<" is used for input re-direction.
  • The value in turn is saved in the variable x.
 This form of read is very useful in shell scripts when the user actually wont be present to provide the input at the terminal.

5 comments: