什么是export
?
有什么区别:
export name=value
和
name=value
答案 0 :(得分:910)
export
使变量可用于子流程。
即,
export name=value
表示变量名可用于从该shell进程运行的任何进程。如果您希望进程使用此变量,请使用export
,然后从该shell运行该进程。
name=value
表示变量作用域仅限于shell,并且不可用于任何其他进程。你可以将它用于(比如)循环变量,临时变量等。
重要的是要注意,导出变量不会使父进程可用。也就是说,在生成的进程中指定和导出变量不会使其在启动它的过程中可用。
答案 1 :(得分:220)
说明其他答案的含义:
$ foo="Hello, World"
$ echo $foo
Hello, World
$ bar="Goodbye"
$ export foo
$ bash
bash-3.2$ echo $foo
Hello, World
bash-3.2$ echo $bar
bash-3.2$
答案 2 :(得分:67)
其他人回答说,导出使变量可用于子壳,这是正确的,但仅仅是副作用。导出变量时,它会将该变量放在当前shell的环境中(即shell调用putenv(3)或setenv(3))。进程的环境在exec中继承,使变量在子shell中可见。
编辑(5年的观点):这是一个愚蠢的答案。 “导出”的目的是使变量“处于随后执行的命令的环境中”,无论这些命令是子单元还是子进程。一个简单的实现就是简单地将变量放在shell的环境中,但这样就无法实现export -p
。
答案 3 :(得分:53)
据说在产生子壳时没有必要以bash出口,而其他人则说完全相反。重要的是要注意子shell(由()
,``
,$()
或循环创建的)和子进程(由名称调用的进程,例如文字{ {1}}出现在您的脚本中)。
这两个结构中常见的是两者都不能将变量传递回父shell。
bash
还有一个混乱的来源:有些人认为'分叉'子过程是那些看不到非导出变量的过程。通常fork()后面跟着exec()s,这就是为什么看起来fork()是寻找的东西,而实际上它是exec()。您可以先使用$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:
命令运行不带fork()的命令,此方法启动的进程也无法访问未导出的变量:
exec
请注意,我们这次没有看到$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export
行,因为我们已经用parent:
命令替换了父shell,所以没有什么可以执行该命令
答案 4 :(得分:28)
export NAME=value
表示对子流程有意义的设置和变量。
NAME=value
用于当前shell进程专用的临时或循环变量。
更详细地说,export
标记环境中的变量名称,该名称在创建时复制到子进程及其子进程。从子进程中没有复制任何名称或值。
常见错误是在等号周围放置一个空格:
$ export FOO = "bar"
bash: export: `=': not a valid identifier
子流程只能看到导出的变量(B
):
$ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
A is . B is Bob
子进程中的更改不会更改主shell:
$ export B="Bob"; echo 'B="Banana"' | bash; echo $B
Bob
标记为导出的变量具有在创建子流程时复制的值:
$ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
[1] 3306
$ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash
Subprocess 1 has B=Bob
Subprocess 2 has B=Banana
[1]+ Done echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
只有导出的变量才会成为环境的一部分(man environ
):
$ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
BOB=Bob
所以,现在它应该像夏天的太阳一样清晰!感谢Brain Agnew,alexp和William Prusell。
答案 5 :(得分:10)
export
将使变量可用于从当前shell派生的所有shell。
答案 6 :(得分:9)
应该注意,您可以导出变量,然后更改该值。变量的值已更改为子进程可用。为变量设置导出后,您必须export -n <var>
删除该属性。
$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset
答案 7 :(得分:7)
正如您可能已经知道的那样,UNIX允许进程拥有一组环境变量,这些变量是键/值对,键和值都是字符串。 操作系统负责分别为每个进程保留这些对。
程序可以通过此UNIX API访问其环境变量:
char *getenv(const char *name);
int setenv(const char *name, const char *value, int override);
int unsetenv(const char *name);
进程还从父进程继承环境变量。操作系统负责创建所有&#34; envars&#34;在创建子进程的那一刻。
除了其他shell之外, Bash 能够根据用户请求设置其环境变量。这是export
存在的原因。
export
是一个Bash命令,用于为Bash设置环境变量。使用此命令设置的所有变量都将由此Bash将创建的所有进程继承。
Bash中的另一种变量是内部变量。由于Bash不仅仅是交互式shell,它实际上是一个脚本解释器,与任何其他解释器(例如Python)一样,它能够保留自己的变量集。应该提到的是,Bash(与Python不同)仅支持字符串变量。
定义Bash变量的表示法是name=value
。这些变量保留在Bash中,与操作系统保存的环境变量无关。
有关Shell Parameters的更多信息(包括变量)
另外值得注意的是,根据Bash参考手册:
可以扩充任何简单命令或功能的环境 暂时通过为参数赋值添加前缀,如上所述 在Shell Parameters。这些赋值语句仅影响 该命令看到的环境。
总结一下:
export
用于在操作系统中设置环境变量。此变量将可用于当前Bash过程创建的所有子进程。答案 8 :(得分:5)
accepted answer暗示了这一点,但我想明确表示与shell builtins的连接:
如前所述,export
将使shell和子系统都可以使用变量。如果export
未使用,则该变量仅在shell中可用,并且只有shell builtins 可以访问它。
即,
tango=3
env | grep tango # prints nothing, since env is a child process
set | grep tango # prints tango=3 - "type set" shows `set` is a shell builtin
答案 9 :(得分:3)
这是另一个例子:
VARTEST="value of VARTEST"
#export VARTEST="value of VARTEST"
sudo env | grep -i vartest
sudo echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"
sudo bash -c 'echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"'
只有使用导出VARTEST,才能在sudo bash -c'...'中使用VARTEST的值!
有关更多示例,请参阅:
bash-hackers.org/wiki/doku.php/scripting/processtree
答案 10 :(得分:2)
只是为了显示环境中导出的变量(env)与不在环境中的非导出变量之间的区别:
如果我这样做:
$ MYNAME=Fred
$ export OURNAME=Jim
然后只有$ OURNAME出现在env中。变量$ MYNAME不在env。
中$ env | grep NAME
OURNAME=Jim
但变量$ MYNAME确实存在于shell
中$ echo $MYNAME
Fred
答案 11 :(得分:2)
UNIX的两位创建者Brian Kernighan和Rob Pike在他们的“UNIX编程环境”一书中解释了这一点。谷歌的标题,你会很容易找到一个PDF版本。
它们在3.6节中讨论shell变量,并专注于在该节末尾使用export
命令:
如果要在子shell中访问变量的值,则应使用shell的export命令。 (您可能会想到为什么无法将变量的值从子shell导出到其父级。)
答案 12 :(得分:1)
虽然在讨论中没有明确提到,但是从bash中生成子shell时没有必要使用export,因为所有变量都被复制到子进程中。
答案 13 :(得分:0)
默认情况下,脚本中创建的变量仅对当前shell可用;子进程(子shell)将无法访问已设置或修改的值。允许子进程查看值,需要使用export命令。