In che modo `less` prende i dati dallo stdin mentre è ancora in grado di leggere i comandi dall'utente?


47

Come molti di voi hanno fatto molte volte, è conveniente visualizzare testi lunghi usando less:

some_command | less

Ora il suo stdin è collegato a una pipe (FIFO). Come può ancora leggere comandi come su / giù / esci?


15
lesslegge i dati da visualizzare da stdin e legge i comandi da tty. Sono cose diverse.
William Pursell,

2
@WilliamPursell Sì, lo so. Ma c'è solo un flusso di input standard, giusto?
iBug

4
Sì, c'è un flusso di input e un tty. lesslegge dati da stdin e comandi da tty.
William Pursell,

Risposte:


52

Come menzionato da William Pursell , lesslegge le battute dell'utente dal terminale. Apre esplicitamente /dev/ttyil terminale di controllo; che gli fornisce un descrittore di file, separato dall'input standard, dal quale può leggere l'input interattivo dell'utente. Può leggere simultaneamente i dati da visualizzare dal suo input standard, se necessario. (Potrebbe anche scrivere direttamente sul terminale, se necessario.)

Puoi vederlo accadere correndo

some_command | strace -o less.trace -e open,read,write less

Spostati nell'input, esci lesse guarda il contenuto di less.trace: lo vedrai aperto /dev/ttye leggerai sia dal descrittore di file 0 sia da quello che è stato restituito quando è stato aperto /dev/tty(probabilmente 3).

Questa è una pratica comune per i programmi che desiderano assicurarsi di leggere e scrivere sul terminale. Un esempio è SSH, ad esempio quando richiede una password o passphrase.

Come spiegato da schily , se /dev/ttynon può essere aperto, lessleggerà dal suo errore standard (descrittore di file 2). lessL 'uso di è /dev/ttystato introdotto nella versione 177, rilasciata il 2 aprile 1991.

Se provi a correre cat /dev/tty | less, come suggerito da Hagen von Eitzen , lessriuscirà ad aprirsi /dev/ttyma non otterrà alcun input da esso fino a quando catnon lo chiude. Quindi vedrai lo schermo vuoto e nient'altro finché non premi CtrlCper uccidere cat(o ucciderlo in qualche altro modo); quindi lessmostrerà tutto ciò che hai digitato mentre catera in esecuzione e ti consentirà di controllarlo.


4
@HagenvonEitzen Il tuo computer esploderà! È come il modo in cui Kirk e Spock fecero schiantare gli androidi di Mudd.
Barmar,

7
@HagenvonEitzen Wow. Un uso doppiamente inutile del gatto . Sono impressionato.
Andrew Henle,

8
@grawity Penso che il punto di Andrew sia che cat blah |può essere sostituito da < blah, e anche questo non è necessario in questo caso poiché less blahfunziona troppo (bene less -f /dev/tty). Ma la lettura da /dev/ttyun po 'di un caso speciale, e tutte e tre le varianti ( cat /dev/tty | less, less < /dev/ttye less -f /dev/tty) producono risultati diversi.
Stephen Kitt,

1
/ Dev / tty punta sempre in qualche modo al posto giusto? Penserei che dovresti usare / dev / ptsX di solito?
StarWeaver

2
@StarWeaver visualizza questa domanda sulla differenza tra /dev/ttye /dev/pts/....
Stephen Kitt,

26

UNIX fornisce due metodi per leggere l'input degli utenti mentre lo stdin è stato reindirizzato:

  • Il metodo originale è leggere da stderr . Stderr è aperto per la scrittura e la lettura e questo è ancora menzionato in POSIX.

  • Versioni successive di UNIX (intorno al 1979) hanno aggiunto un'interfaccia /dev/ttydriver che consente di aprire il controllo di un processo. Poiché ci sono processi senza un controllo tty, è possibile che un tentativo di apertura /dev/ttyfallisca. Il software scritto amichevole ha quindi un fallback al metodo originale e quindi cerca di leggere da stderr.


11
Leggi da stderr? Ho imparato qualcosa di nuovo.
iBug

1
Sono contento che qualcuno ricordi i vecchi modi.
Giosuè,

3
È il motivo per cui stderr viene utilizzato per la lettura, perché è il meno probabile che sia stato reindirizzato? Non vedo alcuna differenza tra esso e lo stdout (o per quel mater stdin, prima del reindirizzamento).
ctrl-alt-delor

4
Sì, è perché questo è il descrittore di file che ha meno possibilità di essere reindirizzato.
schily

@ ctrl-alt-delor: era / è tipico che le shell funzionassero con stdin, stdout e stderr, essendo tutti dup()licenti della stessa descrizione del file, comunque, tutti aperti sul tty. (Apparentemente POSIX richiede ancora o suggerisce (questa risposta non dice) che stderr sia un FD di lettura / scrittura, non aperto con qualcosa del genere open("/dev/ttyS0", O_WRONLY). La lettura di stderr fallirebbe in quel caso.)
Peter Cordes
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.