Meno riceve l'input da tastiera da stderr?
-
10-07-2019 - |
Domanda
Sto dando un'occhiata al codice per l'utilità 'less', in particolare come ottiene l'input da tastiera. È interessante notare che alla riga 80 di ttyin.c, imposta il descrittore di file da cui leggere:
/*
* 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;
Il descrittore di file non è 2 stderr? Se è così, WTH ?! Pensavo che l'input da tastiera fosse inviato tramite stdin.
È interessante notare che, anche se lo fai ls -l * | less
, al termine del caricamento del file, puoi comunque utilizzare la tastiera per scorrere verso l'alto e verso il basso, ma se lo fai ls -l * | vi
, allora vi urlerà perché non lo fa letto da stdin. Qual è la grande idea? Come sono finito in questa strana nuova terra in cui stderr è sia un modo per segnalare errori sullo schermo che leggere dalla tastiera? Non credo di essere più in Kansas ...
Soluzione
$ 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
Quando si accede a un terminale interattivo, tutti e tre i descrittori di file standard puntano alla stessa cosa: il tuo TTY (o 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
Per convenzione, leggiamo da 0
e scriviamo a 1
e 2
. Tuttavia, nulla ci impedisce di fare diversamente.
Quando la shell esegue ls -l * | less
, crea una pipe dal descrittore di file ls
al less
al descrittore di file open("/dev/tty")
<=>. Ovviamente, <=> non è più in grado di leggere l'input da tastiera dell'utente dal descrittore di file <=> & # 8211; cerca di riavere il TTY come può.
Se <=> non è stato rimosso dal terminale, <=> gli assegnerà il TTY.
Tuttavia, nel caso in cui fallisca ... cosa puoi fare? <=> effettua un ultimo tentativo di ottenere il TTY, supponendo che il descrittore di file <=> sia collegato alla stessa cosa a cui sarebbe associato il descrittore di file <=>, se non fosse reindirizzato.
Questo non è a prova di errore:
$ ls -l * | setsid less 2>/dev/null
Qui, a <=> viene assegnata una propria sessione (quindi non fa più parte del gruppo di processi attivi del terminale, causando il fallimento di <=>) e il suo descrittore di file <=> è stato modificato & # 8211; ora <=> esce immediatamente, perché viene inviato a un TTY ma non riesce a ottenere alcun input dell'utente.
Altri suggerimenti
Beh ... prima di tutto, sembra che manchi la chiamata open()
che apre '/ dev / tty'. Utilizza solo il descrittore di file 2 se la chiamata ad open () non riesce. Su un sistema Linux standard, e probabilmente su molti Unices, esiste "/ dev / tty" ed è improbabile che causi un errore.
In secondo luogo, il commento in alto fornisce una quantità limitata di spiegazioni sul perché ricadono nel descrittore di file 2. La mia ipotesi è che stdin
, stdout
e stderr
siano praticamente collegati a '/ dev / tty / 'comunque, a meno che non venga reindirizzato. E dal momento che i reindirizzamenti più comuni per stdin e / o stdout (tramite piping o <
/ >
), ma meno spesso per <=>, le probabilità sono che l'utilizzo di <=> sarebbe molto probabilmente ancora connesso alla " tastiera " ;.
La stessa domanda con una risposta alla fine della persona che l'ha posta è su linuxquestions sebbene citino una fonte leggermente diversa da less
. E no, non capisco la maggior parte, quindi non posso fare a meno di questo :)
Sembra essere una funzionalità specifica di Linux che invia input da tastiera a FD 2.