Warum kann ich / dev / stdout nicht mit einem Texteditor lesen?

9

Ich habe gerade angefangen zu lernen, wie alles eine Datei TM unter Linux ist, was mich gefragt hat, was passieren würde, wenn ich buchstäblich aus / dev / stdout lese:

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

( ^CIch töte das Programm, nachdem es hängt).

Wenn ich es mit versuche vim, erhalte ich die undenkbare Meldung: "/ dev / stdout" ist keine Datei. Keuchen!

Was gibt es also, warum erhalte ich Probleme oder Fehlermeldungen, wenn ich versuche, diese "Dateien" zu lesen?

user1717828
quelle
1
Was vim als Datei betrachtet und was unter "Alles ist eine Datei" (keine zugehörige Marke) in * nix zu verstehen ist, ist nicht dasselbe. Siehe zB Nr. 1 und Nr. 2 .
Goldlöckchen

Antworten:

11

Warum bekomme ich Hangups?

Sie bekommen keine "Hangups" von cat(1)und tail(1)sie blockieren nur das Lesen. cat(1)wartet auf Eingabe und druckt sie aus, sobald eine vollständige Zeile angezeigt wird:

$ cat /dev/stdout
foo
foo
bar
bar

Hier habe ich getippt fooEnterbarEnterCTRL- D.

tail(1)Wartet auf die Eingabe und druckt sie nur aus, wenn sie Folgendes erkennen kann EOF:

$ tail /dev/stdout
foo
bar
foo
bar

Hier habe ich nochmal getippt fooEnterbarEnterCTRL- D.

oder Fehlermeldungen

Vim ist der einzige, der Ihnen einen Fehler gibt. Er tut das , weil es läuft stat(2) gegen /dev/stdout, und es findet es nicht hat S_IFREGBit gesetzt.

/dev/stdoutist eine Datei, aber keine reguläre Datei. Tatsächlich gibt es im Kernel einen Tanz, um ihm einen Eintrag im Dateisystem zu geben. Unter Linux:

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

Auf OpenBSD:

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

Auf 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
lcd047
quelle
5

(Fast) alles ist eine Datei, aber nicht alles ist eine normale Datei. Es ist nicht sinnvoll, einen Texteditor für eine spezielle Datei aufzurufen, z. B. ein Verzeichnis, einen Netzwerk-Socket, eine serielle Schnittstelle usw.

Die Datei /dev/stdoutkann abhängig von der Unix-Variante eines von mehreren Dingen sein:

  • eine "spezielle" Datei, typischerweise ein Zeichengerät;
  • ein "magischer" symbolischer Link, der auf die Datei verweist, die der Prozess, der darauf zugreift, in diesem Deskriptor geöffnet hat;
  • eine symbolische Verknüpfung zu einem der oben genannten.

In jedem Fall wird beim Öffnen /dev/stdoutund ähnlichen Dateien ein neuer Dateideskriptor erstellt, der derselben Datei zugeordnet ist, die die Anwendung bereits für Dateideskriptor 1 geöffnet hat. „Standardausgabe“ bedeutet Dateideskriptor 1, und es ist nur eine Konvention, dass dieser Dateideskriptor verwendet wird für die Ausgabe - der Kernel ist das egal.

Wenn Sie ein Programm in einem Terminal ausführen, werden alle drei Standarddeskriptoren (0 = Standardeingabe, 1 = Standardausgabe, 2 = Standardfehler) auf dem Endgerät geöffnet. Beim Lesen von diesem Gerät werden vom Benutzer eingegebene Zeichen zurückgegeben, und beim Schreiben auf dieses Gerät wird Text im Terminalfenster angezeigt. (Bei einem Endgerät gibt es keine Standardmethode, um die angezeigte Ausgabe zu lesen oder Eingaben in diese zu injizieren.)

Wenn Sie ausführen cat /dev/stdout, geschieht genau das Gleiche wie cat /dev/stdinoder cat /dev/stderr, da diese drei Dateideskriptoren mit derselben Datei verbunden sind: Sie werden angewiesen cat, vom Terminal zu lesen. Das ist es, was catohne Argument auch tut.

Wenn Sie ausgeführt haben cat /dev/stdout >foo, /dev/stdoutverweisen Sie auf die Datei foo- dieser Befehl entspricht cat foo >foo. Abhängig von der catImplementierung kann es entweder zu einem Fehler kommen (die GNU-Version beschwert sich darüber, dass „Eingabedatei Ausgabedatei ist“), oder es wird nichts unternommen, weil es aus der fooleeren Datei liest ( >foonur abgeschnitten). Mit einer Version cat, die diesen Sonderfall nicht erkennt, wenn er foonicht leer ist, würde cat /dev/stdout >>foooder das Äquivalent cat foo >>fooden Inhalt der Datei auf unbestimmte Zeit an sich selbst anhängen.

Wenn Sie ausführen vim /dev/stdout, beschwert es sich, weil es nicht weiß, wie ein Terminal bearbeitet werden soll (das macht einfach keinen Sinn).

Gilles 'SO - hör auf böse zu sein'
quelle
2

catund tailsuchen nach optionalem Inhalt, gefolgt von einem Dateiende. /dev/stdoutbleibt offen, also catund tailschau einfach weiter.

Politank-Z
quelle