在shell脚本中运行shell命令时,会生成一个子shell进程。这个进程不是由 生成的吗fork function
?为什么没有导出的变量不会被继承?在 中fork
,所有父进程的上下文都应该复制到子进程中。
答案1
这里的第一个错误是认为 shell 只是fork()
为了执行外部命令而运行,因此 的描述fork()
就是对 shell 操作的描述。实际上,父进程和子进程都做了很多额外的事情。特别是子进程调用execve()
来运行外部命令。
此时,通过阅读手册页execve()
应该会有所启发。系统调用的一个参数是覆盖的过程映像将具有的环境在程序启动时。显然,操作系统并没有传递任何神奇的隐藏环境。shell 必须明确地设计一个环境并将其传递给execvce()
子进程。该环境可以是 shell 喜欢的任何环境。
这引出了第二个错误。环境变量不是 shell 变量。当 shell 程序启动时,它进口环境变量转换为同名的 shell 变量(在一个 shell 中,转换为 shell 函数)。当生成外部命令时,它会出口shell 变量进入它创建并传递给内核的(新)环境execve()
。在此期间,你在脚本中以及与shell 变量影响那些与 shell 进程环境不同的变量。(在程序启动时导入后,shell 进程的环境通常基本保持不变和未使用。)
这 — — 瞧! — — 解释了为什么export
shell 内置函数被称为“export”。
这也解释了诸如 之类的内置函数如何set
查看未导出的变量。它们不涉及用另一个程序覆盖 shell 程序,也不涉及设置要传递给 的新环境execve()
。同样,使用括号创建子 shell 本身并不涉及execve()
,因此不涉及导出 shell 变量来创建环境。