我在 Debian GNU/Linux 9 上。我知道/proc
是特别的,我知道是什么/proc/self
。
这个命令
sh -c '/bin/cat /proc/self/comm - </proc/self/comm'
产量
cat
sh
如果我使用dash
而不是sh
. 但是bash
,ksh
或者zsh
结果是
cat
cat
取而代之/proc/self/stat
的是,/proc/self/comm
我可以确认这两个cat
-s 实际上是同一个过程。显然外壳在引擎盖下有所不同,没关系。现在让我们采取
sh -c '/bin/cat /proc/self/environ - </proc/self/environ'
看了以上,sh
还是dash
期待先看看cat
shell的环境,再看看shell的环境。它似乎有效(两种环境很可能是相同的,所以很难判断一切是否按预期工作,但我的观点是:两者都不environ
是空的)。
使用bash
,ksh
或者zsh
我期望看到cat
两次的环境,但它只打印了一次。分成两种不同的情况:
bash -c '/bin/cat - </proc/self/environ'
什么也不打印,好像environ
是空的;bash -c '/bin/cat /proc/self/environ'
按预期打印一些东西。
到底是怎么回事?这不是comm
or的情况stat
。为什么不environ
一样?
$ uname -a
Linux barbaz 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1 (2018-04-29) x86_64 GNU/Linux
shell 之间的差异是由于进程设置的差异造成的。
dash
在分叉之前设置重定向,所以/proc/self
指向外壳;bash
并zsh
在分叉后设置它们,因此/proc/self
指向新进程。您可以通过以下方式看到这种情况strace -f
:strace -f dash -c '/bin/cat /proc/self/comm - </proc/self/comm'
表演(除其他外)(
/proc/self/comm
在系统调用之前打开clone
,这是进程分叉的地方);strace -f bash -c '/bin/cat /proc/self/comm - </proc/self/comm'
节目(
/proc/self/comm
在调用后打开clone
,在子进程中,8106)。了解为什么
environ
显示为空需要更多解释。当/proc/<pid>/environ
打开时,内核保存一个指向任务的指针的副本mm_struct
,其中包含指向环境的指针。但是execve
,用于启动cat
进程的 ,会为进程创建一个新mm_struct
的。因此,重定向最终指向过时的信息,当cat
读取其输入时,它看不到它的真实环境。它所看到的环境应该是其父环境的副本,但涉及的 shell 在分叉和设置新环境(由 设置execve
)之前对其进行清理。