在 bash 中,运行时
myvar=val mycommand myargs
Run Code Online (Sandbox Code Playgroud)
myvar=val
将被添加到执行环境中mycommand
。
假设 bash 进程调用fork()
创建一个将执行的子进程mycommand
,即mycommand
外部可执行文件或脚本文件。
什么时候添加myvar=val
到环境中,在 bash shell 调用之前还是之后fork()
?换句话说,以下两种可能性中的哪一种实际上发生了?
bash 进程添加myvar=val
到它自己的环境中,然后调用fork()
创建一个将调用execve()
execute的子进程mycommand
,并将myvar=val
作为 bash 进程环境的一部分继承到子进程的环境中。在完成mycommand
子进程的执行和退出后,bash 进程myvar=val
从它自己的环境中删除。
bash 进程调用fork()
创建一个将执行mycommand
的子进程,子进程添加myvar=val
到自己的环境中,然后调用execve()
execute mycommand
。
我的问题源于斯蒂芬对我之前帖子的回复。
在 Bash 中,
_
是一个特殊参数,每次解析命令时,它都会设置为最后一个参数的值。它还具有不可导出的特殊属性,每次执行命令时都会强制执行(参见bind_lastarg
Bash 源代码)。
我想知道当bash进程执行命令时,如果bash没有添加_
到自己的环境中,为什么它需要从自己的环境中删除它?
谢谢。
现实介于您描述的两种可能性之间。Bash 不会添加myvar
到自己的环境中,至少不会像我们通常认为的那样添加到完整的 shell 环境中;它增加myvar
了它的临时环境。然后,它会从临时环境、当前变量上下文和 shell 函数构建导出环境,专门用于新命令,然后在必要时分叉以运行子命令。您可以在 Bash 源代码中将其视为对 的调用maybe_make_export_env
。然后在孩子启动后清理临时环境;寻找dispose_used_env_vars
。
在实践中,这没有任何区别。子命令获得它应该接收的环境,一旦你控制回来,父环境也应该在它那里;除非您打算对 Bash 进行更改,否则这才是最重要的。