Answers:
起初我很惊讶。但是,在阅读了答案并进行了一些调查之后,这似乎很简单。这就是我所发现的。(最后没有惊喜。)
重定向stdin,stdout和stderr之前已按预期连接到同一设备。
#ctrl-alt-delor:~$
#↳ ll /dev/std*
lrwxrwxrwx 1 root root 15 Jun 3 20:58 /dev/stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root 15 Jun 3 20:58 /dev/stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root 15 Jun 3 20:58 /dev/stdout -> /proc/self/fd/1
#ctrl-alt-delor:~$
#↳ ll /proc/self/fd/*
lrwx------ 1 richard richard 64 Jun 30 19:14 /proc/self/fd/0 -> /dev/pts/12
lrwx------ 1 richard richard 64 Jun 30 19:14 /proc/self/fd/1 -> /dev/pts/12
lrwx------ 1 richard richard 64 Jun 30 19:14 /proc/self/fd/2 -> /dev/pts/12
因此,在大多数重定向之后(即stderr),都不会重定向。stderr仍连接到终端。因此,可以读取它来获取键盘输入。
停止以意外方向使用文件的唯一方法是约定,并且管道是单向的。
另一个示例,请尝试:
cat | less
当less
尝试读取终端时,这在一页之后会出错(这并不奇怪,cat
阅读终端也是如此)。
/dev/tty
更神秘,它不是的链接/proc/self
。
#ctrl-alt-delor:~$
#↳ ll /dev/tty
crw-rw-rw- 1 root tty 5, 0 Jun 29 09:18 /dev/tty
看看我当前的控制终端和`/ dev / tty`之间有什么关系?为了一个惊喜。感谢@StephenKitt提供的链接。
当您登录时,stdin,stdout和stderr从您登录的地方连接到终端。更确切地说,通常打开tty,并且stdout和stderr是dup(2)
对第一个文件描述符进行两次操作的结果。这允许从stderr读取以从终端获取输入。
如在另一个答案中提到的,程序从stderr 读取以获取对问题的交互式答复。
由于用户不知道在什么情况下程序会从stderr读取数据,因此故意从另一个程序将数据写入stderr是无用的尝试。
请注意,今天程序通常/dev/tty
仅在无法使用的情况下才首先尝试打开并使用stderr。
自1979年以来,仅从stderr读取的程序通常从未被修改过,此类程序通常包含以下结构:
int i 1;
要么
i =* 2;
是现代C编译器不接受的。结果,今天您极不可能找到一个永远不会打开/dev/tty
而是从stderr读取交互式回复的程序。
stderr
当stdin
重定向(通过管道或其他方式)时,shell连接到tty 吗?或者只是始终连接stderr
到tty?
i =+ 1
是完全有效的C,等于i = (+1)
。当然,前者是参加C比赛的好人选。
/dev/tty
,看这个问题。