3>&1 是否意味着 4>&3 5>&3 等?

Does 3>&1 imply 4>&3 5>&3 etc.?

我希望

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

失败并出现 /proc/self/fd/4: No such file or directory 等错误,但令我惊讶的是,它输出

foo
foo
foo
foo
foo

这就像 3>&1 导致所有以下描述符都被重定向到标准输出,除非我将 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

是否有对此行为的解释?

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是一个特殊的路径。打开它的效果类似于 duping fd 3:fd 4 指向与 fd 3 相同的位置,即 tty。

每个连续的 openat() 调用都会发生同样的事情。尘埃落定后,fd 4、5、6、7 都是 fd 3 的副本。

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

请注意,3>&1 重定向并不重要。 重要的是我们要求 tee 打开 /proc/self/fd/N,其中 N 已被使用。 如果我们去掉 3>&1 并让 tee 从 /proc/self/fd/2 开始。让我们看看:

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

已确认!结果相同。

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

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