下面代码片段中的关键语句(即除了用于打印标签和空行、用于间距的语句之外)成对出现。在每一对中,第一个和第二个语句的形式分别为tty...
和echo $(tty...)
。
echo stdin:
tty
echo $(tty)
echo
echo stdout:
tty <&1
echo $(tty <&1)
echo
echo stderr:
tty <&2
echo $(tty <&2)
如果我获取包含此代码片段的文件(例如,在zsh
or会话中),我会得到以下输出1(之后我添加了行号,以供参考):bash
1 stdin:
2 /dev/pts/8
3 /dev/pts/8
4
5 stdout:
6 /dev/pts/8
7 not a tty
8
9 stderr:
10 /dev/pts/8
11 /dev/pts/8
在此输出中,由(第 7 行)生成的行echo $(tty <&1)
非常突出,原因有两个:
echo $(tty ...)
它是生成的行(即第 3、7 和 11 行)中唯一tty ...
与其前面的生成的对应行(第 2、6 和 10 行)不同的行;和- 它与形式上类似的 的输出(第 11 行)不同
echo $(tty <&2)
。
问:这两个差异如何解释?
作为记录,我试图在 的手册页中找到这些明显异常的解释tty
,但是,据我所知,该页面根本没有解决这些问题2;当然不是明确的3 .
这个问题是由一些代码引发的这个很好的答案我之前的一个问题。
1当然,/dev/pts/
如果我更换终端,之后的实际数字会有所不同,如果你尝试同样的事情,对你来说可能会有所不同。
2事实上,tty
我的系统上可用的手册页的整个描述部分仅包含一句话:“打印连接到标准输入的终端的文件名。”。
3在这里,我保留了一种可能性,即比我拥有更多背景知识的人可能能够推断从tty
的简洁手册页可以看出上面所示的行为。
答案1
tty
(在其标准输出上)报告在其标准输入(其 fd 0)上打开的 tty 设备的名称。
在:
tty <&2
这是哪个缩写
tty 0<&2
shell 将 fd 0 重定向到与 fd 2 上打开的相同资源(dup2(2, 0)
在新进程中执行 a,然后tty
在该进程中运行)。因此,tty
其 fd 0 和 2 上将具有相同的资源,并在 fd 1 上写入 tty两者都打开(如果有)。
同样的情况发生在:
tty <&1
在:
echo "$(tty <&1)"
然而,该命令替换的 fd 1 转到管道(并且 shell 读取另一端的输出),它与 fd 1转到的tty
资源不同。echo
如果您想知道 fd 1 上打开的 tty 并使用命令替换,您需要类似以下内容:
{ echo "$(tty <&3)"; } 3<&1
因此对于正在运行的进程tty
,我们有:
- 3:与外层1相同
- 1:一根管子
- 2:未动过
- 0:与3相同,因此与外部1相同
因此tty
可以将连接到的 tty 设备的路径写入该管道外标准输出。
由于 tty 不需要 fd 3,因此您可以使用以下命令使其更简洁:
{ echo "$(tty <&3 3<&-)"; } 3<&1
也就是说,用完后关闭它,将其复制到fd 0。