bash变量什么时候导出到子shell和/或可由脚本访问? [英] When are bash variables exported to subshells and/or accessible by scripts?
问题描述
对于bash
变量是否导出到子shell以及何时可以通过脚本访问它们,我感到困惑.到目前为止,我的经验使我相信bash变量可自动用于子shell.例如:
I'm confused over whether bash
variables are exported to subshells and when they are accessible by scripts. My experience so far led me to believe that bash variables are automatically available to subshells. E.g.:
> FOO=bar
> echo $FOO
bar
> (echo $FOO)
bar
上面的内容似乎表明bash
变量可在子shell中访问.
The above appears to demonstrate that bash
variables are accessible in subshells.
给出此脚本:
#! /usr/bin/bash
# c.sh
func()
{
echo before
echo ${FOO}
echo after
}
func
我了解在当前shell上下文中调用脚本可以使它访问当前shell的变量:
I understand that calling the script in the current shell context gives it access to the current shell's variables:
> . ./c.sh
before
bar
after
如果我在没有点空格"先例的情况下调用脚本...
If I were to call the script without the "dot space" precedent...
> ./c.sh
before
after
...不是在子shell中调用脚本的情况吗?如果是这样的话,那么当前shell的变量也可用于子shell(正如我从第一个代码块推断的那样),为什么$FOO
对于这种方式运行时对c.sh
不可用?
...isn't it the case that the script is called in a subshell? If so, and it's also true that the current shell's variables are available to subshells (as I inferred from the firstmost code-block), why is $FOO
not available to c.sh
when run this way?
类似地,当c.sh
在括号内运行时,为什么$FOO
也不可用-我理解这意味着在子shell中运行该表达式:
Similarly, why is $FOO
also unavailable when c.sh
is run within parentheses - which I understood to mean running the expression in a subshell:
> (./c.sh)
before
after
(如果这不使本文含太多问题,如果"./c.sh
"和"(./c.sh)
"都在当前shell的子shell中运行脚本,则两种调用方式之间有什么区别?)
(If this doesn't muddy this post with too many questions: if "./c.sh
" and "(./c.sh)
" both run the script in a subshell of the current shell, what's the difference between the two ways of calling?)
推荐答案
(...)
在单独的环境中运行...
,使用以下方法最容易实现(并在bash,dash和大多数其他POSIX-y shell中实现)子外壳程序-也就是说,是通过fork()
修改旧外壳程序而创建的子程序,但不调用任何execv
-family函数.因此,将复制父对象的整个内存状态,包括未导出的shell变量.
(...)
runs ...
in a separate environment, something most easily achieved (and implemented in bash, dash, and most other POSIX-y shells) using a subshell -- which is to say, a child created by fork()
ing the old shell, but not calling any execv
-family function. Thus, the entire in-memory state of the parent is duplicated, including non-exported shell variables.
./other-script
作为完全独立的可执行文件运行other-script
.在调用子外壳程序(不是子外壳程序!)之后,它 not 不会保留未导出的变量.其工作原理如下:
./other-script
, by contrast, runs other-script
as a completely separate executable; it does not retain non-exported variables after the child shell (which is not a subshell!) has been invoked. This works as follows:
- shell调用
fork()
创建一个子代.此时,该子项甚至还复制了未导出的变量状态. - 该子节点接受任何重定向(如果它是
./other-script >>log.out
,则该子节点将open("log.out", O_APPEND)
然后将fdup()
描述符转移到1
,覆盖标准输出). - 该子代调用
execv("./other-script", {"./other-script", NULL})
,指示操作系统将其替换为新的other-script
实例.调用成功后,在孩子的PID下运行的进程是一个全新的程序,只有export
ed变量可以保留.
- The shell calls
fork()
to create a child. At this point in time, the child still has even non-exported variable state copied. - The child honors any redirections (if it was
./other-script >>log.out
, the child wouldopen("log.out", O_APPEND)
and thenfdup()
the descriptor over to1
, overwriting stdout). - The child calls
execv("./other-script", {"./other-script", NULL})
, instructing the operating system to replace it with a new instance ofother-script
. After this call succeeds, the process running under the child's PID is an entirely new program, and onlyexport
ed variables survive.
这篇关于bash变量什么时候导出到子shell和/或可由脚本访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!