3>&1隐含4>&3 5>&3等吗?

时间:2019-11-02 11:52:02

标签: linux bash shell io-redirection proc-filesystem

我希望

echo foo | tee /proc/self/fd/{3..6} 3>&1

由于诸如 / proc / self / fd / 4之类的错误而失败:没有此类文件或目录等,但令我惊讶的是,它输出

foo
foo
foo
foo
foo

这就像3>&1导致以下所有描述符都重定向到stdout,除了如果我将3更改为其他东西(如

)不起作用
$ echo foo | tee /proc/self/fd/{3..6} 4>&1
tee: /proc/self/fd/3: No such file or directory
tee: /proc/self/fd/5: No such file or directory
tee: /proc/self/fd/6: No such file or directory
foo
foo
$ echo foo | tee /proc/self/fd/{4..6} 4>&1
tee: /proc/self/fd/5: No such file or directory
tee: /proc/self/fd/6: No such file or directory
foo
foo

对此行为有解释吗?

1 个答案:

答案 0 :(得分:29)

strace显示了以下系统调用序列:

$ strace -o strace.log tee /proc/self/fd/{3..6} 3>&1
...
$ cat strace.log
...
openat(AT_FDCWD, "/proc/self/fd/3", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4
openat(AT_FDCWD, "/proc/self/fd/4", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 5
openat(AT_FDCWD, "/proc/self/fd/5", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 6
openat(AT_FDCWD, "/proc/self/fd/6", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 7
...

第一行打开/proc/self/fd/3,并为它分配下一个可用的fd编号4。/proc/self/fd/3是一个特殊路径。打开它的效果类似于{fd 3:fd 3:fd 4指向与tty 3 fd 3相同的位置。

每个连续的openat()调用都会发生相同的情况。当尘埃落定时,fds 4、5、6和7都是fd 3的副本。

  • 1→tty
  • 3→tty
  • 4→tty
  • 5→tty
  • 6→tty
  • 7→tty

请注意,3>&1重定向并不重要。 重要的是,我们要求tee在已经使用 N 的地方打开/proc/self/fd/N如果我们摆脱{{ 1}},并从3>&1开始。让我们看看:

/proc/self/fd/2

确认!结果相同。

我们也可以一遍又一遍地重复相同的fd数字。达到fd 6时,我们得到的结果相同。到最后一个fd时,它已经打开了足够的描述符以使跳到6成为可能。

$ echo foo | tee /proc/self/fd/{2..6}
foo
foo
foo
foo
foo
foo