How (and why) use stderr for both reading and writing?

I was surprised at first. However after reading the answers, and doing a little investigation, it seems simple. So here is what I have found. (in the end there was no surprise.)

Before redirection stdin, stdout, and stderr are as expected connected to the same device.

#ctrl-alt-delor:~$
#↳ ll /dev/std*
lrwxrwxrwx 1 root root 15 Jun  3 20:58 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Jun  3 20:58 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Jun  3 20:58 /dev/stdout -> /proc/self/fd/1

#ctrl-alt-delor:~$
#↳ ll /proc/self/fd/*
lrwx------ 1 richard richard 64 Jun 30 19:14 /proc/self/fd/0 -> /dev/pts/12
lrwx------ 1 richard richard 64 Jun 30 19:14 /proc/self/fd/1 -> /dev/pts/12
lrwx------ 1 richard richard 64 Jun 30 19:14 /proc/self/fd/2 -> /dev/pts/12

Therefore after most re-directions (that is if stderr) is not redirected. stderr is still connected to the terminal. Therefore it can be read, to get keyboard input.

The only thing that is stopping the files being used in the unexpected direction is convention, and the pipes are unidirectional.

Another example, try:

cat | less

This goes wrong after a page, when less tries to read the terminal (this is not a surprise, as cat is also reading the terminal).

/dev/tty is more mysterious, it is not a link into /proc/self.

#ctrl-alt-delor:~$
#↳ ll /dev/tty
crw-rw-rw- 1 root tty 5, 0 Jun 29 09:18 /dev/tty

See what relations are between my current controlling terminal and `/dev/tty`? for an explenation. Thanks to @StephenKitt for the link.


When you log in, stdin, stdout and stderr are connected to the terminal from where you log in. To be more exact, the tty is typcally opened and stdout and stderr are a result from two dup(2) operations on the first file descriptor. This allows to read from stderr in order to get input from the termnal.

As mentioned in the other answer, programs read from stderr in order to get an interactive reply on a question.

Since a user cannot know under which circumstances a program reads from stderr, it is a useless attempt to intentionally write data into stderr from another program.

Note that today programs usually first try to open /dev/tty and use stderr only in case that does not work.

Programs that only read from stderr usually have never been modified since before 1979 and such programs usualy contain constructs like:

int i 1;

or

i =* 2;

that are not accepted by modern C compilers. As a result, it is most unlikely that you today will find a program that never opens /dev/tty but rather reads interactive replies from stderr.

Tags:

Pipe

Stderr