从stderr获得键盘输入的更少? [英] Less gets keyboard input from stderr?
问题描述
我正在研究"less"实用程序的代码,特别是它如何获取键盘输入的代码.有趣的是,在ttyin.c的第80行中,它将文件描述符设置为从以下文件读取:
I'm taking a look at the code to the 'less' utility, specifically how it gets keyboard input. Interestingly, on line 80 of ttyin.c, it sets the file descriptor to read from:
/*
* 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;
不是文件描述符2 stderr吗?如果是这样,是什么?我以为键盘输入是通过stdin发送的.
Isn't file descriptor 2 stderr? If so, WTH?! I thought keyboard input was sent through stdin.
有趣的是,即使您执行ls -l * | less
,在文件加载完成后,您仍然可以使用键盘上下滚动,但是如果您执行ls -l * | vi
,则vi会大喊大叫,因为它不会从stdin读取.有什么大主意?我如何最终来到这片陌生的新大陆,在那里stderr既是向屏幕报告错误又是从键盘读取信息的一种方式?我不认为我已经不在堪萨斯州了……
Interestingly, even if you do ls -l * | less
, after the file finishes loading, you can still use the keyboard to scroll up and down, but if you do ls -l * | vi
, then vi will yell at you because it doesn't read from stdin. What's the big idea? How did I end up in this strange new land where stderr is both a way to report errors to the screen and read from the keyboard? I don't think I'm in Kansas anymore...
推荐答案
$ 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
在交互式终端上登录时,所有三个标准文件描述符都指向同一件事:您的TTY(或伪TTY).
When logged in at an interative terminal, all three standard file descriptors point to the same thing: your TTY (or 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
按照惯例,我们从0
读取并写入1
和2
.但是,没有什么可以阻止我们这样做.
By convention, we read from 0
and write to 1
and 2
. However, nothing prevents us from doing otherwise.
当shell运行ls -l * | less
时,它将创建一个从ls
的文件描述符1
到less
的文件描述符0
的管道.显然,less
无法再从文件描述符0
中读取用户的键盘输入.它会尝试将TTY重新找回.
When your shell runs ls -l * | less
, it creates a pipe from ls
's file descriptor 1
to less
's file descriptor 0
. Obviously, less
can no longer read the user's keyboard input from file descriptor 0
– it tries to get the TTY back however it can.
如果less
尚未从终端上拆下,则open("/dev/tty")
会给它TTY.
If less
has not been detached from the terminal, open("/dev/tty")
will give it the TTY.
但是,如果失败了,您该怎么办? less
最后一次尝试获取TTY,假设文件描述符2
附加到了文件描述符0
如果未重定向的情况下将附加在同一对象上.
However, in case that fails... what can you do? less
makes one last attempt at getting the TTY, assuming that file descriptor 2
is attached to the same thing that file descriptor 0
would be attached to, if it weren't redirected.
此不是故障转移:
$ ls -l * | setsid less 2>/dev/null
在这里,为less
提供了自己的会话(因此它不再是终端活动进程组的一部分,从而导致open("/dev/tty")
失败),并且其文件描述符2
也已更改–现在less
立即退出,因为它正在输出到TTY,但无法获得任何用户输入.
Here, less
is given its own session (so it is no longer a part of the terminal's active process group, causing open("/dev/tty")
to fail), and its file descriptor 2
has been changed – now less
exits immediately, because it is outputting to a TTY yet it fails to get any user input.
这篇关于从stderr获得键盘输入的更少?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!