How to redirect stdout+stderr to one file while keeping streams separate? How to redirect stdout+stderr to one file while keeping streams separate? unix unix

How to redirect stdout+stderr to one file while keeping streams separate?


From what I unterstand this is what you are looking for. First I made a litte script to write on stdout and stderr. It looks like this:

$ cat foo.sh #!/bin/bashecho foo 1>&2echo bar

Then I ran it like this:

$ ./foo.sh 2> >(tee stderr | tee -a combined) 1> >(tee stdout | tee -a combined)foobar

The results in my bash look like this:

$ cat stderrfoo$ cat stdout bar$ cat combined foobar

Note that the -a flag is required so the tees don't overwrite the other tee's content.


{ { cmd | tee out >&3; } 2>&1 | tee err >&2; } 3>&1

Or, to be pedantic:

{ { cmd 3>&- | tee out >&3 2> /dev/null; } 2>&1 | tee err >&2 3>&- 2> /dev/null; } 3>&1

Note that it's futile to try and preserve order. It is basically impossible. The only solution would be to modify "cmd" or use some LD_PRELOAD or gdb hack,


Order can indeed be preserved. Here's an example which captures the standard output and error, in the order in which they are generated, to a logfile, while displaying only the standard error on any terminal screen you like. Tweak to suit your needs.

1.Open two windows (shells)

2.Create some test files

touch /tmp/foo /tmp/foo1 /tmp/foo2

3.In window1:

mkfifo /tmp/fifo</tmp/fifo cat - >/tmp/logfile

4.Then, in window2:

(ls -l /tmp/foo /tmp/nofile /tmp/foo1 /tmp/nofile /tmp/nofile; echo successful test; ls /tmp/nofile1111) 2>&1 1>/tmp/fifo | tee /tmp/fifo 1>/dev/pts/1

Where /dev/pts/1 can be whatever terminal display you want. The subshell runs some "ls" and "echo" commands in sequence, some succeed (providing stdout) and some fail (providing stderr) in order to generate a mingled stream of output and error messages, so that you can verify the correct ordering in the log file.