Confused with redirection and file descriptors

Hi all,

I've been looking for the way to send stdout and stderr to different files. Well, actually I really knew how to make it, but I wanted to be sure.
I've found an instruction very interesting which I'm not able to understand:

taken from this site. It says it sends stdout to output.log, stderr to errors.log, and both to final.log.
I know 3 is another file descriptor, but which file does it refers? How does it work?
I think I understand:

  • oraMon.pl 2>&1 1>&3: stderr is redirected to stdout and stdout is redirected to 3
  • tee /tmp/errors.log 3>&1 1>&2: takes the standards output previous command, and saves it to a file. However, I don't understand why 3 is redirected to stdout, and sdout to stderr.

I still have another question. The difference between this two instructions:

I know first one redirects both stdout and stderr to mylog.log. The second one, I read the stderr is redirected to stdout, and stdout is redirected to a file. So I thought both should be the same, but I also read only stdout is saved to a file in the second instruction. Why?

Sorry for this large question, but I'd like to understand redirection and file descriptors.

Thanks a lot.

Albert.

Let's start with the second one:

./command > mylog.log 2>&1

Here, first stdout is redirected from the TTY to a file. After that, stderr is redirected from the TTY to stdout, which already points to a file.

./command 2>&1 > mylog.log

In this line, first stderr is redirected to whatever stdout is pointing at that time. Then stdout is redirected to a file, but that doesn't influence the first redirection anymore.

To explain your first line, let's split it up:

( # start a subshell
  ( # start another subshell
    /path/to/oraMon.pl 2>&1 1>&3 | tee /tmp/errors.log
    # redirect stderr first to stdout, so that tee can read it and then stdout
    # to the new filedescriptor 3 in order to pass it to the outside
  ) 3>&1 1>&2 | tee /tmp/output.log
    # filedescriptor 3 is redirected to stdout, and stdout (as generated by tee)
    # to stderr
) > /tmp/final.log 2>&1
  # redirect stdout to a file and stderr to stdout, capturing both streams

Good shells can create new file descriptors as needed, some even have the ability for TCP or UDP connections without the need for additional programs.

First of all, thanks for your answer.

So, what's the influence of redirect stderr to stdout. It doesn't affect, does it? In other words, any difference between above instruction and:

which only redirects stdout to a file?

On the other hand, to understand the large instruction, I guess I need to understand better what means "subshell", and how tee works, as well as descriptor 3. I'll google...

Regards,

Albert.

There is a difference:

./command 2>&1 > mylog.log

redirects stderr to stdout and stdout to a file (without influencing each other). This way, the error messages can be used in a pipe (redirects stdout to stdin)

./command 1> mylog.log

only redirects stdout, and stderr will always be printed to the console, no matter what.

As for the complex instruction:

  • tee reads from stdin, and prints it to stdout and the file given as an argument. That's useful if you want to see messages as they come and save them to a file.
  • Sub shells allow you to run commands without influencing the parent shell, in this case to direct messages around. Another popular use is to put an independent, long running portion of a script into the background.
  • file descriptor 3 isn't strictly defined. Usually, in a UNIX environment, a program knows 3 file descriptors (fds):
    [list]
  • 0 is stdin
  • 1 is stdout
  • 2 is stderr
    [/list]
    Just as with a C program you can open additional fds for reading, writing, or both.

Thanks a lot pludi. Now it's quite more clear for me.

Albert.