Linux I/O Redirection
Updated June 01, 2005
Created October 11, 2001


Autogenerated Site Map
Search this Site!:
Search this site powered by FreeFind

Cool commands


Capturing stderr with tee
Swapping stderr and stdout


[root@server /root]# (((./cmd | tee stdout.txt) 3>&1 1>&2 2>&3 \
| tee stderr.txt) 3>&1 1>&2 2>&3) 1>out.txt 2>err.txt

The following section will walk through the theory behind this command. Once you have a general understanding of this theory, you should be able to easily regenerate this entire command without notes.
  1. Contents of the ./cmd script


  2. 
    #!/bin/sh
    #You can use this sample script for testing.  The echo
    #    statements explain how this script works.
    echo "This is Standard Out" >&1
    echo "This is Standard Error" >&2
    

  3. Results from running the ./cmd script


  4. 
    [root@server /root]# ./cmd
    This is Standard Out
    This is Standard Error
    [root@server /root]# 
    

    Although you see both lines printed on the screen, behind the scenes one actually went to stdout and the other went to stderr. If you were to do a pipe, only stdout goes through the pipe. Normally this is the desired effect.

  5. Capturing stdout


  6. The following will capture a copy of stdout and save it to a file called "stdout.txt"

    
    [root@server /root]# ./cmd | tee stdout.txt
    

    stdout goes through the pipe and tee is able to save a copy of it to the file "stdout.txt"; however, we just lost control of stderr. stderr will not go through the pipe, instead it goes directly to our display.

  7. Gaining control of stderr and stdout.


  8. Lets gain control again of stderr and stdout. We do this by surrounding our command with a set of parenthesis.

    
    [root@server /root]# (./cmd | tee stdout.txt)
    

  9. Swapping stdout and stderr.


  10. Now that we have captured stdout, we wish to capture stderr using tee as well. The pipe will only accept stdout, so we must swap stderr and stdout to do this.

    Note: The switch is using the standard variable switch method -- 3 variables (buckets) are required to swap 2 variables with each other. (you have 2 variables and you need to switch the contents - you must bring in a 3rd temporary variable to hold the contents of one value so you can properly swap them).

    
    [root@server /root]# (./cmd | tee stdout.txt) 3>&1 1>&2 2>&3
    

  11. Capturing stderr


  12. Now that we have swapped our stdout and stderr, lets hook up tee once again. tee will now capture stderr (tee believes that it is really stdout because stdout is the only thing that can come through the pipe).

    
    [root@server /root]# (./cmd | tee stdout.txt) 3>&1 1>&2 2>&3 \
    | tee stderr.txt
    

  13. Gaining control of stderr and stdout, for the 2nd time.


  14. Tee grabs stderr, but once again the channel that doesn't go through the pipe gets sent to the display and we loose it. Lets capture both our stderr and stdout, once again, by using parenthesis.

    
    [root@server /root]# ((./cmd | tee stdout.txt) 3>&1 1>&2 2>&3 \
    | tee stderr.txt)
    

  15. Swapping stdout and stderr back to their normal state.


  16. Now we have, once again, captured both stderr and stdout for our use. Currently they are reversed. Lets switch them back for proper use in our pipeline. Again, lets use the standard variable switch to swap them around.

    
    [root@server /root]# ((./cmd | tee stdout.txt) 3>&1 1>&2 2>&3 \
    | tee stderr.txt) 3>&1 1>&2 2>&3
    

  17. Gaining control of stderr and stdout, for the 3rd time.


  18. At this point we have swapped stdout and stderr back to their normal positions; however, if we will be manipulating stdout and stderr any further, we should complete this command with either a pipe or another set of parenthesis.

    Since we want to be as complete as possible in this example we will use parenthesis. Using parenthesis will gain control over both stdout and stderr. Using a pipe will only gain control over stdout.

    Note: If we use a pipe or parenthesis the next process that hooks up to this command will see stderr and stdout in their proper place. If we don't add the last set of parenthesis, or go through a pipe, the order will remain messed up.

    
    [root@server /root]# (((./cmd | tee stdout.txt) 3>&1 1>&2 2>&3 \
    | tee stderr.txt) 3>&1 1>&2 2>&3)
    

  19. Redirecting stdout and stderr to separate files


  20. Now lets do something productive with stdout and stderr so that we can really prove that everything went back to their proper place. Lets tell our command to redirect stdout to "out" and stderr to "err".

    
    [root@server /root]# (((./cmd | tee stdout.txt) 3>&1 1>&2 2>&3 \
    | tee stderr.txt) 3>&1 1>&2 2>&3) 1>out.txt 2>err.txt
    

    Note: This last step is optional, normally you would insert your other required commands here, commands that would more than likely operate on stdout.

    Please note that the results for "out" and "err" are the same as when you run the following command. This proves that we restored stdout and stderr back to their normal usable posisitions. The above command; however, gives us the capability to copy out stdout and stderr using tee and still be able to use stdout and stderr like we always have.

    
    [root@server /root]# ./cmd 1>out.txt 2>err.txt
    


Capturing stderr in one file and stderr and stdout combined in another file

I had a request for stderr in 1 file and stderr and stdout combined in another file so here it is:


Here is our testing command we will use to generate both stderr 
and stdout on proper channels:
root@server:~> (echo out >&1; echo err >&2)
out
err
And here is the command to do the work:
root@server:~> (((echo out >&1; echo err >&2) 3>&2 2>&1 1>&3 | \
tee stderr.txt ) 3>&2 2>&1 1>&3 ) > combined.txt 2>&1
root@server:~> cat stderr.txt
err
root@server:~> cat combined.txt
out
err
root@server:~>

Please keep in mind when reading a book or web page with command line documentation
that the trailing slash signifies continuation of the current line. The reason for
this is due to the line width available on the screen and printed page. Note that
the trailing slash must be the last character on the line followed by enter. Spaces,
tabs, etc., may not apear after the trailing backslash because that does not signify
line continuation but rather some form of escape character. There are two ways that
you may enter this information at the command line:

1. Exactly as show, with the backslashes, followed by enter marks or

(((echo out >&1; echo err >&2) 3>&2 2>&1 1>&3 | \
tee stderr.txt ) 3>&2 2>&1 1>&3 ) > combined.txt 2>&1


2. Remove the trailing backslashes and do not press enter after each line, just word wrap
the lines together at the command prompt.

(((echo out >&1; echo err >&2) 3>&2 2>&1 1>&3 | tee stderr.txt ) 3>&2 2>&1 1>&3 ) > combined.txt 2>&1

Other Good Reading:

jobcontrol.html
man bash

Search this Site!:
Search this site powered by FreeFind

Homepage: http://www.cpqlinux.com
Site Map: http://www.cpqlinux.com/sitemap.html