13

I just started learning how Everything Is A FileTM on Linux, which made me wonder what would happen if I literally read from /dev/stdout:

$ cat /dev/stdout 
^C
$ tail /dev/stdout 
^C

(The ^C is me killing the program after it hangs).

When I try with vim, I get the unthinkable message: "/dev/stdout" is not a file. Gasp!

So what gives, why am I getting hangups or error messages when I try to read these "files"?

1
  • 1
    What vim considers a file and what is meant by "everything is a file" (no associated trademark) in *nix are not the same thing. See e.g. #1 and #2.
    – goldilocks
    Commented May 8, 2015 at 17:08

4 Answers 4

14

why am I getting hangups

You aren't getting "hangups" from cat(1) and tail(1), they're just blocking on read. cat(1) waits for input, and prints it as soon as it sees a complete line:

$ cat /dev/stdout
foo
foo
bar
bar

Here I typed fooEnterbarEnterCTRL-D.

tail(1) waits for input, and prints it only when it can detect EOF:

$ tail /dev/stdout
foo
bar
foo
bar

Here I typed again fooEnterbarEnterCTRL-D.

or error messages

Vim is the only one that gives you an error. It does that because it runs stat(2) against /dev/stdout, and it finds it doesn't have the S_IFREG bit set.

/dev/stdout is a file, but not a regular file. In fact, there's some dance in the kernel to give it an entry in the filesystem. On Linux:

$ ls -l /dev/stdout
lrwxrwxrwx 1 root root 15 May  8 19:42 /dev/stdout -> /proc/self/fd/1

On OpenBSD:

$ ls -l /dev/stdout
crw-rw-rw-  1 root  wheel   22,   1 May  7 09:05:03 2015 /dev/stdout

On FreeBSD:

$ ls -l /dev/stdout
lrwxr-xr-x  1 root  wheel  4 May  8 21:35 /dev/stdout -> fd/1

$ ls -l /dev/fd/1
crw-rw-rw-  1 root  wheel  0x18 May  8 21:35 /dev/fd/1
5

(Almost) everything is a file but not everything is a regular file. It doesn't make sense to call a text editor on something that is a special file such as a directory, a network socket, a serial port, etc.

The file /dev/stdout can be one of several things depending on the unix variant:

  • a “special” file, typically a character device;
  • a “magic” symbolic link that points to the file that the process accessing it has open on this descriptor;
  • a symbolic link to one of the above.

In any case, opening /dev/stdout and similar files creates a new file descriptor that's associated with the same file that the application already has open on file descriptor 1. “Standard output” means file descriptor 1, and it's only a convention that this file descriptor is used for output — the kernel doesn't care.

When you run a program in a terminal, all three standard descriptors (0 = standard input, 1 = standard output, 2 = standard error) are opened on the terminal device. Reading from that device returns characters typed by the user, and writing to that device displays text in the terminal window. (There's no standard way, given a terminal device, to read the output that it displays or to inject input into it.)

When you run cat /dev/stdout, that does exactly the same thing as cat /dev/stdin or cat /dev/stderr, because these three file descriptors are connected to the same file: it tells cat to read from the terminal. That's what cat with no argument does too.

If you ran cat /dev/stdout >foo, then /dev/stdout would refer to the file foo — that command is equivalent to cat foo >foo. Depending on the cat implementation, it might either error out (the GNU version complains that “input file is output file”), or it might do nothing because it reads from the file foo which is empty (>foo just truncated it). With a version of cat that doesn't detect this special case, if foo is not empty, then cat /dev/stdout >>foo or the equivalent cat foo >>foo would append the content of the file to itself indefinitely.

When you run vim /dev/stdout, it complains because it doesn't know how to edit a terminal (that just doesn't make sense).

2

cat and tail are looking for optional content followed by an end of file. /dev/stdout remains open, so cat and tail just keep looking.

-5

please try these

sudo su
chmod +x /dev/stdout
chmod +x /dev/stderr
exit su

I tried and worked and you will learn by trying :)

I don't know why it's necessary? explain it anybody?

stdout permissions info stdin permissions info MY GOAL  HAPPY OF THE END

7
  • Welcome to Unix & Linux! Brevity is acceptable, but fuller explanations are better.
    – Kusalananda
    Commented Aug 28, 2021 at 21:53
  • Brevity vs. fuller explanations are irrelevant when an answer is completely devoid of anything related to the question at hand. There's no reason whatsoever that adding the execute permission to /dev/stdout and others would matter. Also, there's no such thing as /dev/stderror, and exit doesn't take string argument (just a number).
    – ilkkachu
    Commented Aug 28, 2021 at 22:16
  • @Kusalananda Thanks, but I have been same problem with question owner and I fix this way Also echo 'something' > /dev/stdout ` /dev/stdout permission denied error`, solved this way on me Commented Aug 28, 2021 at 22:17
  • @Master_n_Master echo 'something' >/dev/stdout doesn't make sense. echo is already writing to standard output without the redirection.
    – Kusalananda
    Commented Aug 28, 2021 at 22:25
  • 1
    Note that the solution in that question is to remove the redirection to /dev/stdout, which shouldn't have been there from the start anyway.
    – Kusalananda
    Commented Aug 28, 2021 at 23:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .