Skip to content

            Lost ?  |  Need an account:
 
Stream Redirection PDF Print E-mail
(2 votes, average 5.00 out of 5)
Written by Tom Hirt   
Tuesday, 24 February 2009 13:06
Article Index
Stream Redirection
Standard Input
Standard Output
Standard Error
Combined Output
All Pages

Stream Redirection


Under normal circumstances every Unix program has three streams opened for it when it starts up, one for input, one for output, and one for printing diagnostic or error messages. These are typically attached to the user's terminal (see tty(4)) but might instead refer to files or other devices, depending on what the parent process chose to set up.

-Taken from  the BSD Library Functions Manual for STDIN(3)

The input stream is referred to as Standard Input or stdin, the ouput stream as Standard Output or stdout and the Error stream as Standard Error or stderr.  As a systems admins, we often have need for input/output redirection, to many reasons for which to discuss within the context of this article.  However, we will highlight a few real-world use-cases for input/output redirection to which you'll be able to reference as a guide within the context of your own environment for further use.

Input / Output Definitions
stdin from file
0<
stdin with delimiter 0<<
stdout overwrite file
1>
stdout append file 1>>
stderr overwrite file
2>
stderr append file 2>>

Standard Input or STDIN


STDIN is typically taken from your keyboard. However, using input redirection, we can redirect the contents of a file as the input for a command.  This is quite simply accomplished by appending a "0< FILENAME " to the end of a give command:

For example, we see in the following diagram a typical STDIN scenario where a prompt seeking STDIN, asks the user to provide input via the keyboard in order to remove the file some_file.txt.

$ touch some_file.txt
$ rm -i some_file.txt
rm: remove regular empty file `some_file.txt'? yes
$ echo $?
0

Using this example, we can redirect STDIN providing an answer file so that the command completes automatically without prompting for confirmation via the keyboard.  In the following example, we have created a text file named command_list that contains one line with the word "yes".  We again run the command rm but this time redirecting STDIN to our answer file, command_list.

$ cat command_list
yes

$ touch some_file.txt

$ ls
command_list  some_file.txt

$ rm -i some_file.txt 0< command_list
rm: remove regular empty file `some_file.txt'?

$ echo $?
0

$ ls
command_list

The results are exactly as we expected.  The command completed successfully, removing the file some_file.txt while receiving it's input to the confirmation prompt from our answer file, command_list.

We can further simply the syntax by omitting the "0" with the same result:

$ cat command_list
yes

$ touch some_file.txt

$ ls
command_list  some_file.txt

$ rm -i some_file.txt < command_list
rm: remove regular empty file `some_file.txt'?

$ echo $?
0

$ ls
command_list

Here is another example where we display the contents of a file:

$ cat 0< some_file.txt
This is the contents of some_file.txt

$

We can also make use of a delimiter by the use of a '0<< DELIMITER' (the zero can be omitted to simplify the syntax.)  For example:

$ wall << MY_DELIMITER
> hi everyone,
> we have maintenance scheduled in the next 5 minutes.
> we will be rebooting the system.
>
> Please save all work immediately!
>
> Thanks,
> -sysadmin
> MY_DELIMITER
$
Broadcast message from thirt (Wed Feb 25 16:51:46 2009):

hi everyone,
we have maintenance scheduled in the next 5 minutes.
we will be rebooting the system.

Please save all work immediately!

Thanks,
-sysadmin

In the above example, we used the delimiter MY_DELIMITER to provide a multi-line input stream to wall to announce scheduled maintenance to our users.  As you can see, the input stream begins with the first delimiter MY_DELIMITER and terminates with the second MY_DELIMITER, everything in-between is sent as STDIN to wall.


Standard Output or STDOUT


STDOUT can be thought of as the output container produced by a given process.  Most programs will usually default their STDOUT to a screen buffer device such as the system console or a terminal like your X terminal.  So for example, when running the command ls, the output that is produces is sent to our connected X terminal:

$ ls
command_list  some_file.txt

So in the example above, we see a simple directory listing of our working directory.  The highlighted output from 'ls' was sent to STDOUT which happened to be our X terminal.

We can now redirect the output of ls to a file by the use of our output modifier 1>.  When using a output modifier, if the target file already exists, its contents will be overwritten.  If the target does not exist, a new file will be created.

$ ls 1> file_list.txt

$ echo $?
0

$ cat file_list.txt
command_list
file_list.txt
some_file.txt

As you can see, the output which had previously be sent to our screen was redirected to a newly created file called file_list.txt. Like input redirection, we can drop the 1 from our syntax to simply the command.

$ ls > file_list.txt

$ cat file_list.txt
command_list
file_list.txt
some_file.txt

Rerunning a command with the > will only overwrite the contents of what had previously been stored in the target file:

$ echo "one" > file_list.txt

$ echo "two" > file_list.txt

$ echo "three" > file_list.txt

$ cat file_list.txt
three


Appending STDOUT


Appending of STDOUT to a target can be a very valuable tool to you for logging and other such utilities on a system.  In the above example, with each iteration of the command echo, the targeted output's contents were replaced with the commands most recent output.  You can append the output to STDOUT by the use of >> as the output modifier.  For example:

$ cat /dev/null > file_list.txt

$ echo "First Time:" >> file_list.txt

$ ls >> file_list.txt

$ echo "Second Time:" >> file_list.txt

$ ls >> file_list.txt

$ cat file_list.txt
First Time:
command_list
file_list.txt
some_file.txt
Second Time:
command_list
file_list.txt
some_file.txt

In the above, we began by zeroing out the file using the overwrite output modifier, '>'.  We then append, '>>' to the text "First Time:" followed by a directory listing, followed by the text "Second Time:" followed by a directory listing.  I've highlighted the output to help illustrate this example.

Although the above was a trivial example, in the following diagram, we've created a simple file monitoring program that makes use of the date command to log when a file trigger_file appears on the system. Lets take a look:

$ infant_loop=0

$ while [ $infant_loop -eq 0 ]; do
if [ -e trigger_file ]; then
echo -n `date` >> logfile.txt;
echo ' - trigger_file found on system, will now clean-up' >> logfile.txt;
rm -rf ./trigger_file;
fi; sleep 1;
done &

[1] 23809

$ touch trigger_file

$ touch trigger_file

$ touch trigger_file

$ kill -9 23809

$ cat trigger_file
Tue Feb 24 17:58:13 EST 2009 - trigger_file found on system, will now clean-up
Tue Feb 24 18:01:54 EST 2009 - trigger_file found on system, will now clean-up
Tue Feb 24 18:02:26 EST 2009 - trigger_file found on system, will now clean-up

Still a very basic example, but you can now begin to see how powerful stream redirection can be.


Standard Error or STDERR


STDERR can also be thought of as a output container, but different from STDOUT in that its contents are of errors from the running process.  Also like STDOUT, STDERR usually defaults it's output to a screen buffer device like the console or a X terminal. Redirecting STDERR can also be useful for a variety of tasks; we will not go into all of them, but will highlight a couple examples to give you an idea.

When running find on the root of your file-system as a non-privileged user, your console will often times become polluted with Permission denied errors making it very difficult to sift through the output distinguishing the search string from the errors:

$ find / -name some_filename.txt -print
find: /usr/lib64/audit: Permission denied
find: /usr/libexec/utempter: Permission denied
find: /lost+found: Permission denied

......Output Truncated.......

We know that we don't have permissions to all of these folders, but for the ones we do, we would like find to search in them but less all the permission denied errors.  We can do this by the use of the STDERR output modifier 2>.  Using the STDERR output modifier, we can now choose to output all the errors to a text file (for further analysis) or we can just discard them altogether.  In the first example, we'll send the errors to a text file:

$ find / -name some_filename.txt -print 2> error_log.txt
/home/thirt/some_filename.txt

$

As you can see, running find this time produced a much more clean output that only shows the exact hits of our search criteria.  If we like, we can now go back and exam the contents of error_log.txt to see if there was anything of further interest.  We could have also just as easily discarded the output as seen in our next example:

$ find / -name some_filename.txt -print 2> /dev/null
/home/thirt/some_filename.txt

$

Here, we sent all the errors to the black hole, /dev/null.  This can be useful when you know the command you are running will generate errors but you do not wish to see them.

Appending STDERR


Just like STDOUT, we can use the STDERR append modifier 2>> if we would like the output of our command to be appended to a file rather than overwriting the contents.  For example:

$ ls NO_ACCESS_TO_THIS_DIR 2>> error_log.txt

$ find . -name some_filename.txt 2>> error_log.txt
./some_filename.txt

$ cat error_log.txt
ls: NO_ACCESS_TO_THIS_DIR: Permission denied
find: ./NO_ACCESS_TO_THIS_DIR: Permission denied

$

From the above example, we see our first command ls completes with no output sent to the screen and STDERR sent to error_log.txt.  The second command, find, sends the results of the search to our screen (STDOUT) and any errors (STDERR) to error_log.txt.  Upon further inspection of error_log.txt, we see both commands threw errors but because we redirected STDERR, we never saw them until we inspected the contents of error_log.txt.


Combined Output


The final part of our stream redirection discussion focuses on combined out.  Leveraging what we have learned thus far, we may now combine both the STDOUT and STDERR streams into one file. A typical use case for this is system logging.  We often see jobs scheduled through crond or at that redirect their output to STDOUT and/or STDERR for historical records of the transpired events.  This can prove to be a very helpful tool when trying to understand why last night's batch process failed to run properly.

In this example, we look at a basic syntax to combine both STDOUT and STDERR into a single file:

$ find . -name some_filename.txt 2>> error_log.txt 1>> error_log.txt
$ cat error_log.txt
./some_filename.txt
find: ./NO_ACCESS_TO_THIS_DIR: Permission denied
$

Notice the use of our append modifiers >> for both STDOUT and STDERR.  Had we forgotten to use the append modifier, we would have lost the output from STDOUT.  When combining the redirection for STDOUT and STDERR, STDOUT is always written first followed by STDERR.  So depending on if you used the append or overwrite modifier for STDERR, your results will be quite different.  I'll demonstrate with a couple examples.

STDOUT  =  write,  STDERR = append:

$ find . -name some_filename.txt 1> error_log.txt 2>> error_log.txt
$ cat error_log.txt
./some_filename.txt
find: ./NO_ACCESS_TO_THIS_DIR: Permission denied
$

STDOUT = write,  STDERR = write:

$ find . -name some_filename.txt 1> error_log.txt 2> error_log.txt
$ cat error_log.txt
find: ./NO_ACCESS_TO_THIS_DIR: Permission denied
$

STDOUT = append,  STDERR = write:

$ find . -name some_filename.txt 1>> error_log.txt 2> error_log.txt
$ cat error_log.txt
find: ./NO_ACCESS_TO_THIS_DIR: Permission denied
$

So what we have learned, in order to preserve the output of both STDOUT and STDERR in a combined redirection, the STDERR modifier must be set to append or the contents of STDOUT will be lost.

Now although the above examples have helped us better understand the roll of the STDOUT and STDERR modifiers, we had to type a lot more than what is necessary.  Lets lose some keystrokes and simplify our syntax.  We'll start by using a combined output that will overwrite the target file's contents:

$ find . -name some_filename.txt > error_log.txt 2>&1
$ cat error_log.txt
./some_filename.txt
find: ./NO_ACCESS_TO_THIS_DIR: Permission denied

Our syntax from above with use of the single > followed by the file-name and then a 2>&1 tells our interpreter to combine both STDOUT and STDERR, and overwrite the contents of our target file with their output.  For our final example, we combine both STDOUT and STDERR, but this time, appending to the contents of our target file:

$ echo "THIS FILE HAS CONTENT" > error_log.txt
$ find . -name some_filename.txt >> error_log.txt 2>&1
$ cat error_log.txt
THIS FILE HAS CONTENT
./some_filename.txt
find: ./NO_ACCESS_TO_THIS_DIR: Permission denied
$

As expected, the contents of the file were not lost as we used the append modifier, >>, to combine the output into the existing file.

This concludes our article on Stream Redirection, we hope you found this helpful!


Add this page to your favorite website
AddThis Social Bookmark Button
Comments
Add New Search
Write comment
Name:
Email:
 
Website:
Title:
UBBCode:
[b] [i] [u] [url] [quote] [code] [img] 
 
 
:D:):(:0:shock::confused:8):lol::x:P:oops::cry::evil::twisted::roll::wink::!::?::idea::arrow:
 
Please input the anti-spam code that you can read in the image.

!joomlacomment 4.0 Copyright (C) 2009 Compojoom.com . All rights reserved."

Last Updated on Monday, 02 March 2009 15:57
 

Forum Activity

Author: Cogterrit
May.18.12
Author: Cogterrit
May.18.12
Author: Cogterrit
May.18.12
Author: Cogterrit
May.17.12

Online Stats

Guests Online: 81
Members Online: 1