用或不用导出定义一个variables
什么是export
?
有什么区别:
export name=value
和
name=value
export
使variables可用于子stream程。
那是,
export name=value
意味着variables名称可用于您从该shell进程运行的任何进程。 如果您希望进程使用此variables,请使用export
,然后从该shell运行进程。
name=value
意味着variables作用域被限制在shell中,并且不可用于任何其他进程。 你会用这个(说)循环variables,临时variables等
请注意,导出variables不会使父进程可用。 也就是说,在派生进程中指定和导出variables并不会在启动它的进程中可用。
为了说明其他答案的内容:
al$ foo="Hello, World" al$ echo $foo Hello, World al$ bar="Goodbye" al$ export foo al$ bash bash-3.2$ echo $foo Hello, World bash-3.2$ echo $bar bash-3.2$
其他人已经回答说,出口使variables可用于subhells,这是正确的,但仅仅是一个副作用。 当你输出一个variables的时候,它把这个variables放在当前shell的环境中(比如shell调用putenv(3)或者setenv(3))。 一个进程的环境是通过execinheritance的,使得这个variables在subhells中可见。
有人说,在产生子壳体时没有必要用bash来输出,而有些则说是相反的。 注意子shell(由()
, $()
或者循环创build的子shell)和subprocess(通过名称调用的进程,例如脚本中出现的文字bash
()
之间的区别很重要。 无论输出状态如何,子壳将可以访问来自父级的所有variables。 另一方面,subprocess只能看到导出的variables。 这两个结构中常见的是,既不能将variables传递回父shell。
$ 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:
还有一个混乱的根源:有些人认为“分叉”子stream程是没有看到非导出variables的stream程。 通常,fork()紧跟着exec(),这就是为什么看起来fork()是要查找的东西,而实际上它是exec()。 您可以先执行不带fork()的命令,然后使用此方法启动的进程也将无法访问未导出的variables:
$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd execd process: export
请注意,这次我们没有看到parent:
line,因为我们用exec
命令replace了父shell,所以没有什么可以执行的。
export NAME=value
设置和variables的export NAME=value
对subprocess有意义。
NAME=value
当前shell进程临时或循环variables的私有NAME=value
。
更详细地说, export
在创build时复制到subprocess及其subprocess的环境中标记variables名称。 没有名字或值从子stream程中被复制过来。
-
一个常见的错误是在等号周围放置一个空格:
$ export FOO = "bar" bash: export: `=': not a valid identifier
-
只有导出的variables(
B
)被子过程看到:$ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash A is . B is Bob
-
子stream程中的更改不会更改主shell:
$ export B="Bob"; echo 'B="Banana"' | bash; echo $B Bob
-
标记为导出的variables在创build子stream程时复制了值:
$ 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
-
只有导出的variables成为环境的一部分(
man environ
):$ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB" BOB=Bob
所以现在应该和夏天的太阳一样清楚! 感谢Brain Agnew,alexp和William Prusell。
应该指出,你可以导出一个variables,然后改变它的值。 variables的更改值将可用于subprocess。 一旦为variables设置了export -n <var>
您必须执行export -n <var>
来删除该属性。
$ K=1 $ export K $ K=2 $ bash -c 'echo ${K-unset}' 2 $ export -n K $ bash -c 'echo ${K-unset}' unset
export
将使variables对当前shell分支的所有shell有效。
正如你可能已经知道的那样,UNIX允许进程有一组环境variables,它们是键/值对,键和值都是string。 操作系统负责分别为每个进程保留这些对。
程序可以通过这个UNIX API访问它的环境variables:
-
char *getenv(const char *name);
-
int setenv(const char *name, const char *value, int override);
-
int unsetenv(const char *name);
进程也从父进程inheritance环境variables。 操作系统负责在创buildsubprocess时创build所有“envars”的副本。
除其他shell之外, Bash能够根据用户请求设置其环境variables。 这是export
存在。
export
是一个Bash命令来为Bash设置环境variables。 所有用这个命令设置的variables都会被Bash创build的所有进程inheritance。
更多关于Bash的环境
Bash中的另一种variables是内部variables。 由于Bash不只是交互式shell,它实际上是一个脚本解释器,就像任何其他解释器(例如Python)一样,它能够保持自己的一组variables。 应该提到的是Bash(不像Python)只支持stringvariables。
定义Bashvariables的符号是name=value
。 这些variables保留在Bash中,与操作系统保存的环境variables无关。
更多关于Shell参数 (包括variables)
另外值得注意的是,根据Bash参考手册:
任何简单命令或函数的环境都可以通过在参数赋值前添加它来临时扩充,如Shell参数中所述 。 这些赋值语句只影响该命令看到的环境。
总结一下:
-
export
用于在操作系统中设置环境variables。 这个variables将可用于当前Bash进程创build的所有subprocess。 - Bashvariables表示法(name = value)用于设置局部variables只能用于bash的当前进程
- 以另一个命令为前缀的Bashvariables表示法仅为该命令的作用域创build环境variables。
这是又一个例子:
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}"'
只有使用export VARTEST,sudo bash -c'…'才能使用VARTEST的值!
更多的例子请看:
-
bash-hackers.org/wiki/doku.php/scripting/processtree
只是为了显示在环境中的导出variables(env)和不在环境中的非导出variables之间的区别:
如果我这样做:
$ MYNAME=Fred $ export OURNAME=Jim
那么只有$ OURNAME出现在env中。 variables$ MYNAME不在env中。
$ env | grep NAME OURNAME=Jim
但是variables$ MYNAME确实存在于shell中
$ echo $MYNAME Fred
UNIX的两位创造者Brian Kernighan和Rob Pike在他们的书“UNIX编程环境”中解释了这一点。 谷歌的标题,你会很容易find一个PDF版本。
它们在第3.6节中介绍了shellvariables,并着重介绍了在该节最后使用的export
命令:
当你想让一个variables的值在子shell中可用时,应该使用shell的export命令。 (你可能想到为什么没有办法将一个variables的值从一个子shell导出到它的父项)。
虽然在讨论中没有明确提到,但是当从bash内部产生一个子shell时不需要使用export,因为所有的variables都被复制到了subprocess中。
接受的答案意味着这一点,但我想明确的连接到shell builtins:
正如已经提到的那样, export
会为shell和子项提供一个variables。 如果不使用export
,variables将只在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 it's a shell builtin
默认情况下,脚本中创build的variables只能用于当前shell; subprocess(子shell)将无法访问已设置或修改的值。 允许subprocess查看值,需要使用export命令。