正如你们大多数人已经做过很多次的那样,使用以下命令查看长文本很方便less
:
some_command | less
现在它的标准输入已连接到管道 (FIFO)。它如何仍然读取向上/向下/退出等命令?
答案1
正如所提到的威廉·珀塞尔,less
从终端读取用户的击键。它显式打开/dev/tty
,控制终端;这给它一个与标准输入分开的文件描述符,它可以从中读取用户的交互式输入。如有必要,它可以同时从其标准输入读取数据以进行显示。 (也可以写如有必要,直接到终端。)
你可以通过运行看到这种情况发生
some_command | strace -o less.trace -e open,read,write less
移动输入、 exit less
,并查看 的内容less.trace
:您将看到它 open /dev/tty
,并从文件描述符 0 和打开时返回的文件描述符/dev/tty
(可能是 3)读取。
对于希望确保从终端读取和写入的程序来说,这是常见的做法。一个例子是 SSH,例如当它要求输入密码或密码短语时。
作为解释了经过狡猾的,如果/dev/tty
无法打开,less
将从其标准错误(文件描述符2)中读取。less
的使用/dev/tty
是在 1991 年 4 月 2 日发布的版本 177 中引入的。
如果你尝试跑步cat /dev/tty | less
,如建议经过哈根·冯·艾岑,less
将成功打开,但在关闭/dev/tty
之前不会从中获取任何输入。cat
所以你会看到屏幕空白,什么也没有,直到你按下CtrlC杀死cat
(或以其他方式杀死它);然后less
将显示您在cat
运行时输入的任何内容,并允许您控制它。
答案2
当标准输入被重定向时,UNIX 提供了两种方法来读取用户输入:
原来的方法是读取标准错误。 Stderr 已开放供写入和阅读,POSIX 中仍然提到这一点。
后来的 UNIX 版本(大约 1979 年)添加了一个
/dev/tty
驱动程序接口,允许打开进程的控制 tty。由于存在没有控制 tty 的进程,因此尝试打开可能/dev/tty
会失败。因此,友好的编写软件会回退到原始方法,然后尝试从 stderr 读取。