出口是干什么用的?
有什么区别:
export name=value
and
name=value
出口是干什么用的?
有什么区别:
export name=value
and
name=value
当前回答
这里还有一个例子:
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的值!
更多的例子见:
http://mywiki.wooledge.org/SubShell bash-hackers.org/wiki/doku.php/scripting/processtree
其他回答
只是为了显示环境中导出的变量(env)和环境中未导出的变量之间的区别:
如果我这样做:
$ MYNAME=Fred
$ export OURNAME=Jim
那么只有$OURNAME出现在环境中。变量$MYNAME不在环境中。
$ env | grep NAME
OURNAME=Jim
但是变量$MYNAME在shell中确实存在
$ echo $MYNAME
Fred
Export将使该变量对当前shell派生的所有shell可用。
您可能已经知道,UNIX允许进程拥有一组环境变量,这些变量是键/值对,键和值都是字符串。 操作系统负责为每个进程分别保存这些对。
程序可以通过以下UNIX API访问它的环境变量:
Char *getenv(const Char *name); Int setenv(const char *名称,const char *值,Int重写); Int unsetenv(const char *name);
进程还从父进程继承环境变量。在创建子进程时,操作系统负责创建所有“envars”的副本。
Bash和其他shell一样,能够根据用户请求设置其环境变量。这就是出口存在的意义。
export是Bash设置环境变量的命令。用这个命令设置的所有变量都将被这个Bash创建的所有进程继承。
更多关于Bash中的环境
Bash中的另一种变量是内部变量。由于Bash不仅仅是交互式shell,它实际上是一个脚本解释器,就像任何其他解释器(例如Python)一样,它能够保留自己的一组变量。值得一提的是,Bash(与Python不同)只支持字符串变量。
定义Bash变量的符号是name=value。这些变量保存在Bash内部,与操作系统保存的环境变量无关。
更多关于Shell参数(包括变量)
另外值得注意的是,根据Bash参考手册:
任何简单命令或函数的环境都可以扩充 临时用参数赋值作为前缀,如前所述 在Shell Parameters中。这些赋值语句只影响 该命令所看到的环境。
总结一下:
Export命令用于设置操作系统中的环境变量。这个变量以后将对当前Bash进程创建的所有子进程可用。 Bash变量符号(name=value)用于设置局部变量仅对当前Bash进程可用 另一个命令前缀的Bash变量表示法仅为该命令的范围创建环境变量。
作为现有答案的另一个推论,让我们重新表述问题陈述。
“我是否应该导出”的答案与“您的后续代码是否运行隐式访问此变量的命令?”的答案相同。
对于正确记录的标准实用程序,可以在该实用程序手册页的ENVIRONMENT部分中找到答案。例如,git手册页提到GIT_PAGER控制使用哪个实用程序浏览来自git的多页输出。因此,
# XXX FIXME: buggy
branch="main"
GIT_PAGER="less"
git log -n 25 --oneline "$branch"
git log "$branch"
将无法正常工作,因为您没有导出GIT_PAGER。(当然,如果您的系统已经将变量声明为导出到其他地方,则该错误不可重现。)
我们显式地引用了变量$branch,而git程序代码并没有在任何地方引用系统变量分支(它的名字是小写的,这也表明了这一点;但是许多初学者也错误地使用大写字母作为私有变量!有关讨论,请参阅正确的Bash和shell脚本变量大写),因此没有理由导出分支。
正确的代码应该是这样的
branch="main"
export GIT_PAGER="less"
git log -n 25 --oneline "$branch"
git log -p "$branch"
(或者等效地,你可以显式地在每次git调用前加上临时赋值
branch="main"
GIT_PAGER="less" git log -n 25 --oneline "$branch"
GIT_PAGER="less" git log -p "$branch"
如果不是很明显,shell脚本语法
var=value command arguments
的执行期间临时将var设置为value
command arguments
并将其导出到命令子进程,然后将其恢复到之前的值,该值可能是未定义的,或定义为不同的-可能为空的-值,如果之前是这样,则未导出。)
对于内部的、临时的或文档记录不佳的工具,您只需要知道它们是否会默默地检查它们的环境。这在实践中并不重要,除了一些特定的用例之外,例如将密码或身份验证令牌或其他秘密信息传递给运行在某种容器或隔离环境中的进程。
If you really need to know, and have access to the source code, look for code which uses the getenv system call (or on Windows, with my condolences, variations like getenv_s, w_getenv, etc). For some scripting languages (such as Perl or Ruby), look for ENV. For Python, look for os.environ (but notice also that e.g. from os import environ as foo means that foo is now an alias for os.environ). In Node, look for process.env. For C and related languages, look for envp (but this is just a convention for what to call the optional third argument to main, after argc and argv; the language lets you call them anything you like). For shell scripts (as briefly mentioned above), perhaps look for variables with uppercase or occasionally mixed-case names, or usage of the utility env. Many informal scripts have undocumented but discoverable assignments usually near the beginning of the script; in particular, look for the ?= default assignment parameter expansion.
作为一个简短的演示,下面是一个shell脚本,它调用一个Python脚本,该脚本查找$NICKNAME,如果未设置则返回到默认值。
#!/bin/sh
NICKNAME="Handsome Guy"
demo () {
python3 <<\____
from os import environ as env
print("Hello, %s" % env.get("NICKNAME", "Anonymous Coward"))
____
}
demo
# prints "Hello, Anonymous Coward"
# Fix: forgot export
export NICKNAME
demo
# prints "Hello, Handsome Guy"
作为另一个切题的评论,让我重申一下,您只需要导出一个变量一次。很多初学者都喜欢货邪代码
# XXX FIXME: redundant exports
export PATH="$HOME/bin:$PATH"
export PATH="/opt/acme/bin:$PATH"
但通常情况下,您的操作系统已经将PATH声明为export,因此这是更好的编写方式
PATH="$HOME/bin:$PATH"
PATH="/opt/acme/bin:$PATH"
或者重构成
for p in "$HOME/bin" "/opt/acme/bin"
do
case :$PATH: in
*:"$p":*) ;;
*) PATH="$p:$PATH";;
esac
done
# Avoid polluting the variable namespace of your interactive shell
unset p
这避免了在PATH中添加重复的条目。
有人说在生成子shell时不需要在bash中导出,而其他人则说完全相反。注意子shell(由()、' '、$()或循环创建的子shell)和子进程(按名称调用的进程,例如脚本中出现的bash文本)之间的区别是很重要的。
子shell将可以访问来自父变量的所有变量,而不管它们的导出状态如何。 子进程只能看到导出的变量。
这两种构造的共同之处在于它们都不能将变量传递回父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:
还有一个困惑的来源:一些人认为“分叉”子进程是那些看不到非导出变量的子进程。通常fork()后面紧跟着exec(),这就是为什么看起来fork()是要找的东西,而实际上是exec()。你可以先用exec命令运行没有fork()ing的命令,由这个方法启动的进程也不能访问未导出的变量:
$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export
注意,这次我们没有看到parent:行,因为我们已经用exec命令替换了父shell,所以没有任何东西可以执行该命令。