On Tue, Jan 22, 2013 at 06:56:31AM -0500, Steven W. Orr wrote:
> By that logic,
> 
> foo 2>&1 | bar
> 
> should not work, but it does. It takes stderr and dups it to stdout, and 
> *then* takes stdout and send it to a pipe.

Incorrect.  The pipeline is created first, and *then* the dup (2>&1) is
performed.

Also, "takes stderr and dups it to stdout" is backwards.  It is taking
stdout (1) and dup'ing that and putting the duplicate FD into stderr (2).
I like to read "2>&1" as "make 2 be a copy of 1".

So, in chronological order:

0) Bash sets up a new execution environment (forking, or saving FDs in
   temporary FDs, or whatever it has to do to clean the slate).
1) A pipe is created.  This gives us two new FDs.
2) Bash creates two new processes and connects stdout of the first process
   to the pipe's "write FD", and connects stdin of the second process to
   the pipe's "read FD".
3) Within the first child process, stdout (which happens to be pointing
   to the pipe) is duplicated, and the duplicate FD is stored in stderr (2).
   Therefore, stderr is *also* pointing to the pipe.
4) The first process execs "foo".  The second process execs "bar".
   Meanwhile, the parent process (bash) waits for them to complete.
5) foo and bar do whatever they do.  Eventually they stop running.  Bash
   wakes up and moves on to the next command.

Reply via email to