2009-09-17 15 views
12

Ich schaue mir den Code für das Dienstprogramm 'less' an, speziell wie es Tastatureingabe erhält. Interessanterweise auf der Leitung 80 von ttyin.c, setzt er der Dateideskriptor zum Lesen:Less bekommt Tastatureingabe von Stderr?

 /* 
     * Try /dev/tty. 
     * If that doesn't work, use file descriptor 2, 
     * which in Unix is usually attached to the screen, 
     * but also usually lets you read from the keyboard. 
     */ 
    #if OS2 
     /* The __open() system call translates "/dev/tty" to "con". */ 
     tty = __open("/dev/tty", OPEN_READ); 
    #else 
     tty = open("/dev/tty", OPEN_READ); 
    #endif 
     if (tty < 0) 
      tty = 2; 

Ist das nicht Descriptor 2 stderr-Datei? Wenn ja, WTH ?! Ich dachte, dass die Tastatureingabe über die Standardeingabe gesendet wurde.

Interessanterweise, auch wenn Sie ls -l * | less tun, nachdem die Datei geladen wurde, können Sie die Tastatur verwenden, um nach oben und nach unten, aber wenn Sie ls -l * | vi tun, dann wird vi an Sie schreien, weil es nicht von stdin gelesen hat . Was ist die große Idee? Wie bin ich in diesem fremden neuen Land gelandet, in dem stderr sowohl Fehler auf dem Bildschirm anzeigt als auch von der Tastatur liest? Ich glaube nicht, dass ich in Kansas bin ...

+0

BTW, wenn Sie 'ls -l * schreiben | vim -', vim wird ähnliche Magie ausführen. – ephemient

Antwort

19
 
$ ls -l /dev/fd/ 
lrwx------ 1 me me 64 2009-09-17 16:52 0 -> /dev/pts/4 
lrwx------ 1 me me 64 2009-09-17 16:52 1 -> /dev/pts/4 
lrwx------ 1 me me 64 2009-09-17 16:52 2 -> /dev/pts/4 

Wenn angemeldet bei einem interativen Terminal zeigen alle drei Standarddateideskriptoren auf dasselbe: Ihre TTY (oder Pseudo-TTY).

 
$ ls -fl /dev/std{in,out,err} 
lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stdin -> fd/0 
lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stdout -> fd/1 
lrwxrwxrwx 1 root root 4 2009-09-13 01:57 /dev/stderr -> fd/2 

Vereinbarungs lesen wir von 0 und schreiben zu 1 und 2. Nichts hindert uns jedoch daran, etwas anderes zu tun.

Wenn Ihre Shell ls -l * | less ausgeführt wird, erstellt er ein Rohr aus ls 's Dateideskriptors 1 zu less' s Dateideskriptors 0. Offensichtlich less kann nicht mehr die Tastatureingabe des Benutzers aus Dateideskriptor lesen 0 – es versucht, die TTY zurück, aber es kann.

Wenn less nicht vom Terminal getrennt wurde, gibt open("/dev/tty") es dem TTY.

Allerdings, falls das scheitert ... was können Sie tun? less macht einen letzten Versuch, die TTY zu erhalten, unter der Annahme, dass der Dateideskriptor 2 an dieselbe Sache angefügt ist, an die der Dateideskriptor 0 angehängt wäre, wenn er nicht umgeleitet würde.

Diese ist nicht ausfallsicher:

 
$ ls -l * | setsid less 2>/dev/null 

Hier wird less seine eigene Sitzung gegeben (so ist es nicht mehr ein Teil der aktiven Prozessgruppe des Terminals, was open("/dev/tty") zum Scheitern verurteilt) und seine Datei Descriptor 2 wurde geändert – jetzt less wird sofort beendet, weil es auf eine TTY ausgibt, aber es keine Benutzereingaben erhalten.

+3

+1, sehr vollständig. –

+0

Oh, ich sehe es jetzt. Da stderr nichts weiter ist als ein Dateideskriptor, der tatsächlich mit dem Terminal verbunden ist, kann er lesen oder schreiben, wie es ihm gefällt. DAS IST COOL! Danke, Ephemient. – Michael

+0

Wäre nicht der Deskriptor '2' nur zum Schreiben geöffnet? –

2

Nun ... zuerst, Sie scheinen zu fehlen der open() Aufruf, der '/ dev/tty' öffnet. Es verwendet nur den Dateideskriptor 2, wenn der Aufruf von open() fehlschlägt. Auf einem Linux-Standardsystem und wahrscheinlich vielen Unices ist "/ dev/tty" vorhanden und wird wahrscheinlich keinen Fehler verursachen.

Zweitens ist der Kommentar am Anfang eine begrenzte Menge an Erklärung gibt, warum sie zu Dateideskriptor zurückgreifen 2. Meine Vermutung ist, dass stdin, stdout und stderr sind ziemlich verbunden ‚/ dev/tty /‘ wie auch immer, es sei denn, umgeleitet. Und da die häufigsten Umleitungen für Standard und/oder Standard (über Rohrleitungen oder </>), aber weniger oft für stderr, sind Chancen auf, dass die Verwendung stderr am ehesten noch mit der "Tastatur" verbunden sein würde.

+0

Der Grund für die Verwendung von stderr ist, dass es sich bei stdin/stdout eher um Pipes handelt, die von der Laich-Shell erstellt wurden. Piping in oder aus weniger ist ein Noop, aber funktioniert. Das Umleiten von stderr eines weniger Befehls hat jedoch nur einen geringen Wert und wird wahrscheinlich nicht durchgeführt. Also wetten, dass stderr ist "wirklich" das Endgerät ist eine vernünftige Schätzung. –

1

Die gleiche Frage mit einer Antwort letztlich von der Person, die es fragte, ist auf linuxquestions, obwohl sie etwas andere Quelle von less Zitat. Und nein, ich verstehe nicht, die meisten davon, so kann ich nicht darüber hinaus, dass :) helfen

-2

Es scheint Linux spezifische Funktionalität zu sein, die Tastatureingabe zu FD sendet 2.

+1

eklatant falsch. Versuchen Sie es mit einem anderen UNIX-System. – ephemient