Linux proc/pid/fd 的 stdout 是 11 吗?
使用重定向到文件的 stdout 执行脚本。所以 /proc/$$/fd/1 应该指向该文件(因为 stdout fileno 是 1)。然而,该文件的实际 fd 是 11。请解释为什么。
这是会话:
$ cat hello.sh
#!/bin/sh -e
ls -l /proc/$$/fd >&2
$ ./hello.sh > /tmp/1
total 0
lrwx------ 1 nga users 64 May 28 22:05 0 -> /dev/pts/0
lrwx------ 1 nga users 64 May 28 22:05 1 -> /dev/pts/0
lr-x------ 1 nga users 64 May 28 22:05 10 -> /home/me/hello.sh
l-wx------ 1 nga users 64 May 28 22:05 11 -> /tmp/1
lrwx------ 1 nga users 64 May 28 22:05 2 -> /dev/pts/0
Executing a script with stdout redirected to a file. So /proc/$$/fd/1 should point to that file (since stdout fileno is 1). However, actual fd of the file is 11. Please, explain, why.
Here is session:
$ cat hello.sh
#!/bin/sh -e
ls -l /proc/$/fd >&2
$ ./hello.sh > /tmp/1
total 0
lrwx------ 1 nga users 64 May 28 22:05 0 -> /dev/pts/0
lrwx------ 1 nga users 64 May 28 22:05 1 -> /dev/pts/0
lr-x------ 1 nga users 64 May 28 22:05 10 -> /home/me/hello.sh
l-wx------ 1 nga users 64 May 28 22:05 11 -> /tmp/1
lrwx------ 1 nga users 64 May 28 22:05 2 -> /dev/pts/0
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我有一个怀疑,但这很大程度上取决于您的 shell 的行为方式。您看到的文件描述符是:
11:脚本的正常标准输出描述 10 和 11 在 exec 上接近,因此不会出现在
ls
进程中。然而,0-2 是在分叉之前为 ls 做好准备的。我在 dash (Debian Almquist shell) 中看到了这种行为,但在 bash (Bourne Again shell) 中没有看到这种行为。 Bash 在分叉后进行文件描述符操作,并且顺便在脚本中使用 255 而不是 10。在分叉后进行更改意味着它不必恢复父级中的描述符,因此它没有用于 dup2 的备用副本。I have a suspicion, but this is highly dependent on how your shell behaves. The file descriptors you see are:
Descriptors 10 and 11 are close on exec, so won't be present in the
ls
process. 0-2 are, however, prepared for ls before forking. I see this behaviour in dash (Debian Almquist shell), but not in bash (Bourne again shell). Bash instead does the file descriptor manipulations after forking, and incidentally uses 255 rather than 10 for the script. Doing the change after forking means it won't have to restore the descriptors in the parent, so it doesn't have the spare copy to dup2 from.strace
的输出在这里会很有帮助。相关部分是
因此,shell 将现有的 stdout 移动到 10 以上的可用文件描述符(即 11),然后将现有的 stderr 移动到它自己的 stdout 上(由于
>&2
重定向),然后当 ls 命令完成时将 11 恢复到它自己的标准输出。The output of
strace
can be helpful here.The relevant section is
So, the shell moves the existing stdout to an available file descriptor above 10 (namely, 11), then moves the existing stderr onto its own stdout (due to the
>&2
redirect), then restores 11 to its own stdout when thels
command is finished.