Home > front end >  Redirecting stderr to stdout as well as to stderr
Redirecting stderr to stdout as well as to stderr

Time:12-16

I usually have the following: ./myscript > myfile.log 2>&1

I want to have stderr and stdout to be written to myfile.log as well as have stderr to go "stderr" (terminal).

I was looking at tee, but tee is only for stdout.

CodePudding user response:

You can use tee:

{ ./myscript 2>&1 >&3 | tee /dev/stderr >&3; } 3> myfile.out

or

{ ./myscript 2>&1 >&3 | tee /dev/fd/2 >&3; } 3> myfile.out

You might also try:

rm myfile.out; { ./myscript 2>&1 >&3 | tee -a myfile.out >&2; } 3>> myfile.out

but that feels a bit kludgy. I believe this should work as well:

{ ./myscript 2>&1 >&3 | tee -a myfile.out >&2; } 3> myfile.out

and feels slightly less like a kludge.

CodePudding user response:

Try it this way:

$: ./myscript 2> >( tee myfile.log >&2 ) 1>&2

Note the space between 2> and >( is required to keep the syntax unambiguous.

To prove it works as intended, put a filter on with grep.
(I used ls as a simple way to get output on both streams.)

$: ls -ld . bogus 2> >( tee err.log >&2 ) 1>&2 | grep foo >stdout.log
ls: cannot access 'bogus': No such file or directory
drwxr-xr-x 1 P2759474 1049089 0 Dec 15 11:19 .

Output from tee sent to err.log and to console stream 2, or stderr. Stream 1 (stdout) sent wherever stream 2 went, so also to tee, which sends all it's output to its own stream 2, the stderr of the console.

grep couldn't see either, because nothing comes through on stream 1, so it can't filter non-matching lines.

$: ls -l err.log stdout.log
-rw-r--r-- 1 P2759474 1049089 113 Dec 15 11:19 err.log
-rw-r--r-- 1 P2759474 1049089   0 Dec 15 11:19 stdout.log

Everything went to tee's log, nothing to grep's.

$: cat err.log
ls: cannot access 'bogus': No such file or directory
drwxr-xr-x 1 P2759474 1049089 0 Dec 15 11:19 .
  • Related