在 shell 创建将执行命令的子进程之前或之后添加临时环境变量吗?

Tim*_*Tim 1 bash

在 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_lastargBash 源代码)。

我想知道当bash进程执行命令时,如果bash没有添加_到自己的环境中,为什么它需要从自己的环境中删除它?

谢谢。

Ste*_*itt 5

现实介于您描述的两种可能性之间。Bash 不会添加myvar到自己的环境中,至少不会像我们通常认为的那样添加到完整的 shell 环境中;它增加myvar了它的临时环境。然后,它会从临时环境、当前变量上下文和 shell 函数构建导出环境,专门用于新命令,然后在必要时分叉以运行子命令。您可以在 Bash 源代码中将其视为对 的调用maybe_make_export_env。然后在孩子启动后清理临时环境;寻找dispose_used_env_vars

在实践中,这没有任何区别。子命令获得它应该接收的环境,一旦你控制回来,父环境也应该在它那里;除非您打算对 Bash 进行更改,否则这才是最重要的。