web-dev-qa-db-fra.com

Comment `less` prend-il les données de stdin tout en étant capable de lire les commandes de l'utilisateur?

Comme la plupart d'entre vous l'ont fait plusieurs fois, il est pratique d'afficher un texte long en utilisant less:

some_command | less

Maintenant, son stdin est connecté à un tuyau (FIFO). Comment peut-il toujours lire des commandes comme haut/bas/quitter?

47
iBug

Comme mentionné par William Pursell , less lit les frappes de l'utilisateur depuis le terminal. Il ouvre explicitement /dev/tty, le terminal de contrôle; qui lui donne un descripteur de fichier, distinct de l'entrée standard, à partir duquel il peut lire l'entrée interactive de l'utilisateur. Il peut lire simultanément des données à afficher à partir de son entrée standard si nécessaire. (Il pourrait également écrire directement sur le terminal si nécessaire.)

Vous pouvez voir cela se produire en exécutant

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

Déplacez-vous dans l'entrée, quittez less et examinez le contenu de less.trace: vous le verrez ouvert /dev/tty, et lire à la fois le descripteur de fichier 0 et celui qui a été renvoyé lors de son ouverture /dev/tty (probablement 3).

Cette pratique est courante pour les programmes qui souhaitent s’assurer de lire et d’écrire sur le terminal. Un exemple est SSH, par exemple quand il demande un mot de passe ou une phrase secrète.

Comme expliqué par schily , si /dev/tty ne peut pas être ouvert, less lira son erreur standard (descripteur de fichier 2). less utilisation de /dev/tty a été introduit dans la version 177, publiée le 2 avril 1991.

Si vous essayez d'exécuter cat /dev/tty | less, comme suggéré par Hagen von Eitzen , less réussira à ouvrir /dev/tty mais n'en obtiendra aucune entrée tant que cat ne la fermera pas. Vous verrez donc l'écran vide, et rien d'autre jusqu'à ce que vous appuyiez sur CtrlC tuer cat (ou le tuer d'une autre manière); alors less affichera tout ce que vous avez tapé pendant que cat était en cours d'exécution, et vous permettra de le contrôler.

52
Stephen Kitt

UNIX propose deux méthodes pour lire les entrées des utilisateurs pendant que stdin a été redirigé:

  • La méthode originale consiste à lire depuis stderr. Stderr est ouvert pour l'écriture et lecture et ceci est toujours mentionné dans POSIX.

  • Les versions UNIX ultérieures ont ajouté (vers 1979) un /dev/tty interface de pilote qui permet d'ouvrir le tty de contrôle d'un processus. Puisqu'il existe des processus sans tty de contrôle, il est possible qu'une tentative d'ouverture de /dev/tty échoue. Un logiciel écrit convivial a donc un retour à la méthode d'origine et essaie ensuite de lire à partir de stderr.

27
schily