“少”如何从stdin中获取数据,同时仍然能够读取用户的命令?


47

正如大多数人已经做过很多次一样,使用less以下命令查看长文本很方便:

some_command | less

现在,它的标准输入连接到管道(FIFO)。它仍如何读取上/下/退出等命令?


15
less从stdin读取要显示的数据,并从tty读取命令。他们是不同的东西。
威廉·珀塞尔

2
@WilliamPursell是的,我知道。但是只有一个标准输入流,对吗?
iBug

4
是的,有一个输入流和一个tty。 less从标准输入读取数据,从tty读取命令。
William Pursell

Answers:


52

William Pursell所述less从终端读取用户的击键。它显式打开/dev/tty,控制终端;它提供了一个文件描述符,与标准输入分开,它可以从中读取用户的交互式输入。如有必要,它可以同时从标准输入读取数据以显示。(如果需要,它也可以直接写入终端。)

您可以通过运行看到这种情况

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

移动输入,退出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运行时输入的任何内容,并允许您对其进行控制。


4
@HagenvonEitzen您的计算机将爆炸!就像Kirk和Spock导致Mudd的机器人崩溃的方式一样。
Barmar

7
@HagenvonEitzen哇。猫的双重使用。我印象深刻
Andrew Henle

8
@grawity我认为Andrew的观点是cat blah |可以用代替< blah,即使在这种情况下less blah也没有必要,因为它也可以工作(很好less -f /dev/tty)。但是从阅读/dev/tty是一个有点特殊的情况下,和所有的三个变种(cat /dev/tty | lessless < /dev/ttyless -f /dev/tty)产生不同的结果。
Stephen Kitt

1
/ dev / tty是否总是以某种方式指向正确的位置?我认为您通常需要使用/ dev / ptsX吗?
StarWeaver

2
@StarWeaver看到这个问题有关的区别/dev/tty/dev/pts/...
史蒂芬·基特

26

在重定向标准输入后,UNIX提供了两种读取用户输入的方法:

  • 原始方法是从stderr读取。Stderr开放供写作阅读,这在POSIX中仍然提到。

  • 后来的UNIX版本确实在1979年左右添加了一个/dev/tty驱动程序接口,该接口允许打开进程的控制tty。因为有些进程没有控制tty,所以打开尝试/dev/tty失败的可能性很大。因此,友好的书面软件将退回到原始方法,然后尝试从stderr读取。


11
从stderr阅读?学到了新东西。
iBug

1
我很高兴有人记得旧的方式。
约书亚

3
是使用stderr进行读取的原因,因为它最不可能被重定向?我没有看到它和stdout之间有任何其他区别(或者对于重定向前的主stdin)。
ctrl-alt-delor

4
是的,因为这是文件描述符被重定向的机会最少。
schily

@ ctrl-alt-delor:通常情况下,shell与stdin,stdout和stderr一起运行dup(),尽管它们都是相同文件描述的许可证,但是都在tty上打开。(显然POSIX仍然要求或建议(这个答案没有说)stderr是读/写FD,而不用诸如此类的东西打开open("/dev/ttyS0", O_WRONLY)。在这种情况下,读取stderr将会失败。)
Peter Cordes
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.