出口是干什么用的?
有什么区别:
export name=value
and
name=value
出口是干什么用的?
有什么区别:
export name=value
and
name=value
当前回答
默认情况下,在脚本中创建的变量只对当前shell可用;子进程(子shell)将不能访问已设置或修改的值。允许子进程查看这些值,需要使用export命令。
其他回答
这里还有一个例子:
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
虽然在讨论中没有明确提到,但从bash内部生成子shell时没有必要使用export,因为所有变量都复制到子进程中。
只是为了显示环境中导出的变量(env)和环境中未导出的变量之间的区别:
如果我这样做:
$ MYNAME=Fred
$ export OURNAME=Jim
那么只有$OURNAME出现在环境中。变量$MYNAME不在环境中。
$ env | grep NAME
OURNAME=Jim
但是变量$MYNAME在shell中确实存在
$ echo $MYNAME
Fred
为了说明其他答案的意思:
$ 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$
作为现有答案的另一个推论,让我们重新表述问题陈述。
“我是否应该导出”的答案与“您的后续代码是否运行隐式访问此变量的命令?”的答案相同。
对于正确记录的标准实用程序,可以在该实用程序手册页的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中添加重复的条目。