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
我希望
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