我正在使用 Ubuntu 22.04.3 LTS
当我执行时,ls /proc/$$/fd
我得到以下结果
0 1 2 255
但是当我执行时ls /proc/$$/fd/*
我得到了以下结果
ls: 无法访问 '/proc/126708/fd/3': 没有这样的文件或目录 /proc/126708/fd/0 /proc/126708/fd/1 /proc/126708/fd/2 /proc/126708/fd /255
但我不明白为什么我得到了不同的结果
我正在使用 Ubuntu 22.04.3 LTS
当我执行时,ls /proc/$$/fd
我得到以下结果
0 1 2 255
但是当我执行时ls /proc/$$/fd/*
我得到了以下结果
ls: 无法访问 '/proc/126708/fd/3': 没有这样的文件或目录 /proc/126708/fd/0 /proc/126708/fd/1 /proc/126708/fd/2 /proc/126708/fd /255
但我不明白为什么我得到了不同的结果
最重要的是要认识到通配符不是由 'ls' 扩展的 - 它们是由 shell 扩展的。这有两个效果:
在第二个示例中,“ls”实际接收的命令行是五个确切名称的列表,此时已扩展。(诸如 $$ 之类的变量也会扩展。)因此,真正运行的确切命令是:
(您可以使用“forkstat”或“execsnoop”或者可能的“strace -f -e execve -p 126708”来查看这一点。)
当 shell 被要求扩展
*
通配符时,它需要打开目录才能列出其内容 - 这会创建一个文件描述符;在这种情况下,特别是 fd #3。因此,shell 文件描述符的扩展列表是自引用的,并且包含用于生成列表的相同 fd #3。
一旦 shell 完成通配符扩展,它会再次关闭目录的 fd,导致“fd/3”从“实时”/proc/126708 目录中消失。但是,该项目不会从通配符扩展刚刚生成的文件列表中消失 - 一旦它出现,它就在那里,并且将被传递给“ls”。
简而言之,由于
/proc/126708/fd/3
通配符扩展,该条目在通配符扩展期间出现,然后在运行“ls”命令之前消失。您可以通过执行 来获得类似的自引用效果
ls -l /proc/self/fd
,这将列出“ls”本身持有的文件描述符 - 您将看到其中一个对应于 /proc/self/fd 目录。(在这种情况下没有错误消息,因为列表是作为一个步骤完成的。)