运行 exec 命令是否保留调用 shell 的环境变量?如果是这样,为什么?

运行 exec 命令是否保留调用 shell 的环境变量?如果是这样,为什么?

据我了解执行命令将调用 shell 程序替换为命令无需分叉子进程。另外,如果我正确理解导出的变量是传递给其生成的子项的变量。但由于当你执行命令,为什么该命令仍然从调用 shell 继承其变量?

为了说明这种情况(在 Bash 中运行),这里有一个示例:

$ cat vartest1
x=50
y=1
export y
exec ./vartest2

$ cat vartest2
echo x = $x
echo y = $y

$ ./vartest1
x =
y = 1

为什么vartest2继承导出的变量vartest1但不是本地的,如果vartest2不是一个子进程vartest1当运行时执行

答案1

Unix不使用spawn,而是使用fork。 Fork 克隆一个进程(在子进程中具有非常短的差异列表),通常紧接在 exec 之前。 (如评论中所述..) exec 系统调用是将环境变量传递给新进程的地方。父级可以默认使用自己的环境作为新的可执行文件,或者传递其他可能完全不同的东西。

在 bash(可能还有其他 shell)中,命令-c的选项exec可以清除环境。还可以通过variable=value在命令行上的 exec 之前放置来以通常的方式更改环境变量。如果这些事情都没有完成,新的可执行文件将继承 shell 所具有的内容。

请注意,虽然 fork() 在子进程中进行的更改非常少,但 exec() 却进行了大量的更改。例如,信号处理程序被重置。打开的文件句柄可以在 exec 上标记为关闭,这样新的可执行文件就无法获取它们。内存映射从头开始重做。环境变量之类的东西可以作为一组继承或替换。

因此,您对 fork 和 exec 的作用的假设与实际使用有些相反。这里的理念是,fork() 经常用于创建一个新进程,该进程的内存将全部被丢弃给新的可执行文件,因此没有必要进行任何更改或设置它的工作。分叉后,正在运行的程序可以选择继续使用相同的内存(通常设置为写入时复制,根据需要机会克隆内存页),或者使用 exec() 将其完全替换为新程序,从而与父程序解除关联共享内存页面,未对其进行任何更改。环境变量是调用 exec() 后可能(但不一定)保留的少数变量之一。

相关内容