“less”如何从标准输入获取数据,同时仍然能够读取用户的命令?

“less”如何从标准输入获取数据,同时仍然能够读取用户的命令?

正如你们大多数人已经做过很多次的那样,使用以下命令查看长文本很方便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 读取。

相关内容