我的管道中有一系列流程:
cat haystack | grep needle | my_process | less
我的理解是 shell 分叉并同时为每个命令运行 execve 。
在 my_process 中,假设我已经确定了它们的 PID,我如何确定 grep 和 less 是否已完全启动(execve'd)?
答案1
好吧,在 Linux 上,你可以检查:/proc/PID/exe
(p=$BASHPID; /bin/ls -l /proc/$p/exe; exec /bin/ls -l /proc/$p/exe)
... 0 Jan 17 10:34 /proc/17816/exe -> /bin/bash
... 0 Jan 17 10:34 /proc/17816/exe -> /bin/ls
但我真的看不出这有什么好处,外壳程序不会在 之前读取/写入管道exec
,因此即使在 之前有一小段时间窗口,管道也可以无缝工作exec
。事实上,这是一个小的exec
在一段时间内,如果您甚至可以到达那里检查正在运行的程序时已经发生了,我不会感到惊讶。
答案2
这就是继承打开文件描述符的目的。
建立一个 FIFO。在父 shell 中打开一个 close-on-exec 只写文件描述符。所有fork()
ed 子级都会继承它,然后在 时关闭它execve()
。在需要检测 的进程中为其打开一个只读文件描述符execve()
,或者让该进程继承一个已经打开的只读文件描述符。当只写端被 关闭时execve()
,只读端将返回EOF。
为了检测个体execve()
,可推广到多个 FIFO。事实上,到那时你就不用费心去处理 FIFO 了只需使用第二组管道,其写入文件描述符设置为 close-on-exec。
因为你还没有解释这实际上是什么为了,弄清楚如何将其构建到您实际尝试做的事情中,这只是您的任务。
答案3
仅限 Linux 并带有zsh
,
$ autoload zsh/stat
$ (zstat +link /proc/*/fd/0(e'{[[ $REPLY -ef /proc/self/fd/1 ]] &&
reply=$REPLY:h:h/exe}')) | cat
/bin/cat
这为您提供了与在其标准输入上打开的子 shell 的标准输出具有相同管道的进程的可执行文件的路径。所以上面那个时候,cat
已经被执行了。