脚本通常以诸如 之类的 shebang 开头#!/usr/bin/env bash
,它指定要用于执行的 shell。shebang 不存在时的执行行为似乎取决于调用 shell。无论哪种方式,脚本都是从“新”shell 运行的,它不知道调用 shell 中定义的变量和函数。
或者,也可以将脚本source
放入 shell,根据我的理解,这相当于将脚本内容复制粘贴到当前 shell 中。如果在脚本中定义了任何函数或变量,那么它们将在“执行”后保留在调用 shell 中,这可能是不可取的。
这两个选项之间有什么吗?是否有可能将脚本作为调用 shell 的子 shell 执行,这样我们就可以访问调用 shell 中定义的所有内容,但不会修改它(除非可能有export
这样的命令)?
写作(source myscript.sh)
似乎是在做我想做的事;这是正确的方法吗?是否有等效的 shebang 会通过调用产生相同的行为./myscript.sh
?
是正确的方式(标准形式是
.
, 不是source
, 并且.
在 上没有指定目录搜索PATH
)。即使可以编写一个引用父 shell 的 shebang,例如,如果有一个
/proc/parent
指向父 shell 的指针(类似于/proc/self
),它也不可靠,因为父 shell 可能不再存在于磁盘上!例如,如果一个脚本启动,并且它正在运行的 shell 被升级,那么脚本使用的特定 shell 将被替换。POSIX(IEEE 标准 1003.1-2017,第 2.12 节)规定:
因此,您认为子 shell 可以访问调用 shell 中的所有内容是正确的,但对于诸如
export
能够修改父 shell 的环境之类的命令是不正确的。当然,格式也由 POSIX 指定如下:
假设您的脚本中有一个 shebang。它将使用您指定的任何解释器(例如 bash)运行,但作为一个单独的进程,而不是作为一个子 shell。但这仍然可以实现您希望运行的脚本不会修改父 shell 环境的结果。
注意:点
.
命令等同于source
.更新:忘记解决作为脚本运行不会导出任何环境变量的事实,除非
set -a
设置了该选项。但请记住,只有在该选项打开后分配的变量才会被导出。如果这不是您想要的,那么您最好的选择是(. script.sh)
从手册: