我希望
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
对此行为有解释吗?
答案 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的副本。
请注意,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