在 ~/.bash_profile 中设置 PATH 与导出 PATH

njb*_*oot 30 bash path environment-variables profile

在自定义我的 bash 配置文件时有什么区别,哪个更好用?该export命令的文档很少,因为它是一个内置的 cmd。

摘自我的 ~/.bash_profile 版本 1:

#PATH
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:$HOME/bin

#add Homebrew’s sbin to PATH
export PATH=/usr/local/sbin:$PATH
Run Code Online (Sandbox Code Playgroud)

输出: echo $PATH /usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/njboot/bin

摘自第 2 版:

#PATH
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:$HOME/bin

#add Homebrew’s sbin to PATH
export PATH=/usr/local/sbin:$PATH
Run Code Online (Sandbox Code Playgroud)

输出与echo $PATH版本 1env中的相同。也是相同的。

所以:

  • 1) 使用export与显式设置 PATH 有什么好处?
  • 2) 应用时,版本 1 和版本 2 之间是否有任何功能差异?
  • 3)我应该使用哪个,为什么?

mik*_*erv 17

具体回答您的问题:

  1. export 确实设置了$PATH显式。

  2. 否。export为子进程设置环境,但$PATH已为当前环境设置。因此,在第二个示例中,当命令被读入 - 并且 export执行之前- 当前环境的值$PATH被扩展为$PATH单词。

  3. 您应该使用对您来说必要和/或舒适的任何一种。两者在功能上都没有任何区别,因此这主要是风格问题。

POSIX 定义了export内置函数:

shell 将赋予与export指定名称对应的变量的属性,这将使它们处于随后执行的命令的环境中。如果变量名后跟= word,则该变量的值应设置为word

从我的另一个答案

声明 shell 变量和环境变量之间几乎没有区别。因为 export 是一个内置函数,它为下一次调用的进程声明了一个环境变量,但如果你不调用一个,该进程仍然是 shell,所以你的变量会被评估两次。

您可以删除所有导出,而不会对导出的变量产生任何影响,只要您不使用export两次求值即可。两次评估我的意思是:

var1=var2 
export "${var1}=var3"
echo "$var2"
var3
Run Code Online (Sandbox Code Playgroud)

而只是使用:

set -a 
Run Code Online (Sandbox Code Playgroud)

...在脚本的顶部。此后定义的所有变量都将自动exported- 这将包括您之前可能没有export编辑过的变量。或者,您只能set -a对脚本的一部分set +a进行设置,然后再取消设置 - 它也可以用作函数。

但是子shell无论如何都会自动继承变量值,所以:

var1=value
( echo "$(echo "$var1")" )
value
Run Code Online (Sandbox Code Playgroud)

export 在这种情况下没有区别。

但是,如果您的脚本调用另一个脚本或任何其他可执行文件来解释您export编辑过的值而您停止使用export它们,那么这些值在它们的环境中将不再可用。在下面的示例中,我使用 shell 变量$PS1——它定义了交互式 shell 提示的内容——来演示exported 变量的变化如何影响子进程。

export PS1="$(printf "this is another executable\n > ")"
echo exit | sh -i

###OUTPUT###

this is another executable
 > exit
exit
Run Code Online (Sandbox Code Playgroud)

但 ...

PS1="$(printf "this is another executable\n > ")"
echo exit | sh -i

###OUTPUT###

sh-4.3$ exit
exit
Run Code Online (Sandbox Code Playgroud)

但是话又说回来,如果您在调用进程时显式声明环境变量......

PS1="$(printf "this is another executable\n > ")"
{
echo exit | PS1=$PS1 sh -i
echo exit | sh -i
}

###OUTPUT###

this is another executable
 > exit
exit
sh-4.3$ exit
exit
Run Code Online (Sandbox Code Playgroud)

任何ENV首先由 shell 调用的文件,例如.bashrc.profile将为该 shell 的生命周期设置变量值。因此,export在这些文件中设置和编辑的任何变量都将保持该export特征,并在exportshell 的生命周期内或直到它们被unset.

但是,值得注意的是,bashexport某种程度上扩展了内置函数以包含-n选项 - 这使您可以export从变量中删除属性而不unset对其进行调整,但这不是可移植的行为。


pol*_*lym 12

这是一个类似的线程

简短的回答:

https://superuser.com/a/153378/333431

导出的变量会传递给子进程,而非导出的变量则不会。

这意味着您应该使用export变量,如果您打算在子外壳中使用它们。

你可以测试这个:

$ TEST="im_not_here"
$ echo $TEST
im_not_here
$ bash -c 'echo $TEST'
<empty output>
$ export TEST2="im_here"
$ echo $TEST2
im_here
$ bash -c 'echo $TEST2'
im_here
Run Code Online (Sandbox Code Playgroud)

  • 然而,`PATH=/usr/local/sbin:$PATH` 在没有 `export` 的情况下也能正常工作:一旦一个变量被导出,它就会保持导出状态,并且进一步的赋值会修改环境变量。此外,为了澄清 mikeserv 的评论,您不需要 `export` 在子 shell 中使用变量,您需要它们在子程序中使用它们。*Subshel​​l* 是一个技术术语,意思是正在运行的 shell 的“分叉”副本。`(echo $var)` 在子 shell 中运行 `echo `$var` 并查看原始 shell 的内部变量;`sh -c 'echo $var'` 在子程序中运行 `echo $var` 并且只看到环境变量。 (4认同)
  • 您应该澄清 *subshel​​ls* 的含义。`var=val; (echo $var)` 仍然产生 `val`。 (3认同)