我正在使用 Ubuntu 22.04.3 LTS
当我执行时ls /proc/$$/fd
我得到了以下结果
0 1 2255
但当我执行时ls /proc/$$/fd/*
我得到了以下结果
ls:无法访问'/proc/126708/fd/3':没有此文件或目录/proc/126708/fd/0/proc/126708/fd/1/proc/126708/fd/2/proc/126708/fd/255
但我不知道为什么我得到了不同的结果
答案1
最重要的是要意识到通配符不会被 'ls' 扩展 - 它们是由 shell 扩展的。这有两个效果:
在第二个示例中,“ls”实际接收的命令行是五个确切名称的列表,此时已展开。($$ 等变量也已展开。)因此,实际运行的确切命令是:
ls /proc/126708/fd/0 /proc/126708/fd/1 /proc/126708/fd/2 /proc/126708/fd/3 /proc/126708/fd/255
(您可以使用“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 目录。(在这种情况下没有错误消息,因为列表是作为单个步骤完成的。)