2009-09-17 13 views
12

Przyjrzyjmy się kodowi narzędzia "mniej", a konkretnie temu, jak dostaje się wejście z klawiatury. Co ciekawe, na linii 80 ttyin.c, ustawia deskryptor pliku do odczytu z:Mniej pobiera dane z klawiatury ze 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; 

nie jest plik deskryptora 2 stderr? Jeśli tak, WTH ?! Myślałem, że wejście klawiatury zostało wysłane przez stdin.

Co ciekawe, nawet jeśli nie ls -l * | less, po zakończeniu załadunku pliku, nadal można korzystać z klawiatury do przewijania w górę iw dół, ale jeśli nie ls -l * | vi, wtedy vi krzyczeć na ciebie, ponieważ nie czyta ze standardowego wejścia . Jaki jest wielki pomysł? Jak trafiłem na tę dziwną, nową krainę, gdzie stderr jest zarówno sposobem zgłaszania błędów na ekranie, jak i czytania z klawiatury? Nie sądzę, że jestem już w Kansas ...

+0

BTW, jeśli napiszesz 'ls -l * | vim -', vim wykona podobną magię. – ephemient

Odpowiedz

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 

Gdy zalogowany na terminalu interwencyjnym wszystkie trzy standardowe deskryptory plików wskazują na to samo: twój TTY (lub 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 

Umownie możemy odczytać z 0 i pisać do 1 i 2. Jednak nic nie stoi na przeszkodzie, abyśmy postąpili inaczej.

Gdy powłoka działa ls -l * | less, tworzy rura z ls „s deskryptor 1 do less” s pliku deskryptora 0. Oczywiście, less nie może już odczytać danych z klawiatury użytkownika z deskryptora pliku, dlatego próbuje odzyskać TTY, jak tylko może.

Jeśli nie został odłączony less od terminala, open("/dev/tty") da mu TTY.

Jednak w przypadku niepowodzenia ... co możesz zrobić? less wykonuje ostatnią próbę pobrania TTY, zakładając, że deskryptor pliku 2 jest dołączony do tej samej rzeczy, do której zostałby dołączony deskryptor pliku 0, gdyby nie został przekierowany.

Ten nie jest failproof:

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

Tutaj less podano własną sesję (tak, to nie jest już częścią aktywnej grupy procesów terminala, powodując open("/dev/tty") niepowodzenie), a jego plik deskryptor 2 został zmieniony – teraz less kończy działanie natychmiast, ponieważ wysyła do TTY, ale nie otrzymuje żadnych danych wejściowych od użytkownika.

+3

+1, bardzo kompletny. –

+0

Och, widzę to teraz. Ponieważ stderr jest niczym więcej niż deskryptorem pliku, który jest faktycznie podłączony do terminalu, może czytać lub pisać z niego, jak mu się podoba. TO SUPER! Dziękuję, ephemient. – Michael

+0

Czy jednak deskryptor '2' nie byłby otwarty tylko do zapisu? –

2

Cóż ... Po pierwsze, brakuje połączenia open(), które otwiera "/ dev/tty". Używa tylko deskryptora 2, jeśli wywołanie metody open() nie powiedzie się. W standardowym systemie Linux i prawdopodobnie wielu Uniksach istnieje "/ dev/tty" i jest mało prawdopodobne, aby spowodował błąd.

drugie, komentarz na górze zapewnia ograniczoną ilość wyjaśnienie, dlaczego one spaść z powrotem do deskryptora pliku 2. Domyślam się, że stdin, stdout i stderr są dość dużo podłączony do „/ dev/tty /” w każdym razie, chyba że zostanie przekierowany. A ponieważ najczęstsze przekierowania dla stdin i/lub stdout (przez rurociągi lub </>), ale rzadziej dla stderr, szanse na to, że najprawdopodobniej przy użyciu stderr będzie się łączyć z "klawiaturą".

+0

Powodem używania stderr jest to, że stdin/stdout są bardziej prawdopodobne, że są rurami utworzonymi przez powłokę odradzania. Rurociągi do lub z mniej jest odlot, ale działa. Ale przekierowanie stderra mniejszej komendy ma szczególnie małą wartość i prawdopodobnie nie zostanie wykonane. Więc obstawianie stderr jest "naprawdę" urządzeniem końcowym, to rozsądne domysły. –

1

To samo pytanie z odpowiedzią ostatecznie od osoby, która go poprosiła, jest na linuxquestions, chociaż cytuje nieco inne źródło od less. I nie, nie rozumiem większość z nich więc nie mogę pomóc, poza tym :)

-2

Wydaje się być specyficzne dla Linuksa funkcjonalność, która wysyła dane z klawiatury do FD 2.

+1

Fałszywe fałsz. Wypróbuj to na dowolnym innym systemie UNIX. – ephemient

Powiązane problemy