为什么这样做:
# a.sh
setEnv() {
export TEST_A='Set'
}
这不是:
# b.sh
export TEST_B='Set'
例如:
> source a.sh
> setEnv
> env | grep TEST_A
TEST_A=Set
> b.sh
> env | grep TEST_B
我理解为什么运行脚本不起作用以及如何使其工作(source b.sh
等),但我很好奇为什么功能有效。
如果重要的话,这是在OS X上。
答案 0 :(得分:5)
您需要了解 采购 与 执行 脚本之间的区别。
Sourcing 从调用脚本的父shell运行脚本;保留所有环境变量,直到父shell终止(终端关闭,或者重置或重置变量),而
执行从父shell分支新shell,包含export
变量的变量仅保留在子shell的环境中,并在脚本终止时终止
即。在第一种情况下创建的用于保存变量的子shell(假设它是一个环境)不是在单独的子环境的范围内分配,而是仅在父项中添加(例如,想象一个额外的内存单元,由父级维护) )环境,直到你打开会话为止。但是,执行一个脚本,想象一个简单的类比,调用一个函数,其变量存储在堆栈中,在函数调用结束时松散范围。同样,分叉shell的环境在终止时会失去范围。
所以归结到这一点,即使你有一个函数到export
你的变量,如果你没有source
它到当前shell并且只是明白execute
它,不保留变量;即。
# a.sh
setEnv() {
export TEST_A='Set'
}
如果你在shell中运行它
bash script.sh # unlike/NOT source script.sh
env | grep TEST_A
# empty
答案 1 :(得分:4)
执行一个函数本身不会启动像b.sh
这样的新流程。
从手册页(强调最后一句):
FUNCTIONS
A shell function, defined as described above under SHELL GRAMMAR,
stores a series of commands for later execution. When the name of a
shell function is used as a simple command name, the list of commands
associated with that function name is executed. **Functions are executed
in the context of the current shell; no new process is created to
interpret them (contrast this with the execution of a shell script).**
答案 2 :(得分:3)
我理解为什么运行脚本不起作用以及如何使其运行(
source b.sh
等)
因此,您已经了解直接执行b.sh
的事实 - 在子进程中,当前对环境的更改根本不可见 em> process(shell) - 不在当前(shell)进程中定义TEST_B
,因此我们可以将这种情况从图片中删除。< / p>
我很好奇为什么功能有效。
当您source
脚本时,您在当前 shell的上下文中执行它 - 松散地说,就好像您直接键入了脚本的内容一样在提示符处:对环境的任何更改(包括特定于shell的元素,如 shell 变量,别名,函数)对当前shell都是可见的。
因此,在执行source a.sh
之后,函数setEnv
现在在当前shell中可用,并且调用它执行export TEST_A='Set'
,它定义了环境变量TEST_A
in 当前 shell(以及随后创建的子进程会看到它)。
也许您的误解是chepner's helpful answer地址:在类似POSIX的shell中, 函数在当前shell中运行 - 与脚本(在没有source
的情况下运行时)相比,为其创建子进程。
如果重要的话,这是在OS X上。
不是这种情况,因为只使用bash
本身内置的功能。