djechlin
djechlin

Reputation: 60768

How to tee to stderr?

I want to split stdout so that it is printed both to stdout and stderr. This sounds like a job for tee but the syntax is evading me -

./script.sh | tee stderr

Of course, how should stderr actually be referred to here?

Upvotes: 70

Views: 25427

Answers (4)

yurenchen
yurenchen

Reputation: 2483

About /dev/stderr permission

user not always has write permission for

  • /dev/stderr
  • /dev/fd/2
  • /proc/self/fd/2
    (they all link to same pts)

for example, after sudo:

sudo su - nobody -s /bin/bash

nobody@test:/$ ls -lh /dev/stderr /dev/fd/2 /proc/self/fd/2
lrwxrwxrwx 1 root   root    15 Jun 10  2021 /dev/stderr -> /proc/self/fd/2
lrwx------ 1 nobody nogroup 64 Apr  7 01:58 /dev/fd/2 -> /dev/pts/5
lrwx------ 1 nobody nogroup 64 Apr  7 01:58 /proc/self/fd/2 -> /dev/pts/5

nobody@test:/$ echo hell >&2
hell

nobody@test:/$ echo hell >/dev/fd/2
-su: /dev/fd/2: Permission denied

nobody@test:/$ echo hell >/dev/stderr 
-su: /dev/stderr: Permission denied

nobody@test:/$ echo hell > /dev/pts/5
-su: /dev/pts/5: Permission denied

Another choice: awk

nobody@test:/$ echo hell | awk '{print>"/dev/stderr";print}' 
hell
hell

nobody@test:/$ echo ' hell   12 ' | awk '{print|"cat 1>&2";print}'
 hell   12 
 hell   12 

Although there has >"/dev/stderr", but it not really same as it in shell.

Maybe awk is not as performant as tee,
But it's worth noting, about the real stderr.

RTSC

Figure out the difference

To be continue..

Upvotes: 1

brianegge
brianegge

Reputation: 29872

The only cross platform method I found which works in both interactive and non-interactive shells is:

command | tee >(cat 1>&2)

The argument to tee is a file or file handle. Using process substitution we send the output to a process. In the process =cat=, we redirect stdout to stderr. The shell (bash/ksh) is responsible for setting up the 1 and 2 file descriptors.

Upvotes: 92

David W.
David W.

Reputation: 107040

./script.sh 2>&1 >/dev/null | tee stderr.out

That opens STDERR to STDOUT, and then disposes of STDOUT.

Upvotes: -3

Nicholas Wilson
Nicholas Wilson

Reputation: 9685

./script.sh | tee /dev/fd/2

Note that this is dependant on OS support, not any built-in power in tee, so isn't universal (but will work on MacOS, Linux, Solaris, FreeBSD, probably others).

Upvotes: 66

Related Questions