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?
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?
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.
./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).
/dev/stderr permissionuser not always has write permission for
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
awknobody@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.
Figure out the difference
To be continue..
./script.sh 2>&1 >/dev/null | tee stderr.out
That opens STDERR to STDOUT, and then disposes of STDOUT.