设置环境变量的BASH脚本无法正常工作。

我已经编写了以下脚本,以在需要时设置一些环境变量:
#!/bin/sh
export BASE=/home/develop/trees
echo $BASE
export PATH=$PATH:$BASE
echo $PATH

在我的终端上,我可以看到以下命令和结果:脚本运行了,但是变量在最后没有被设置。
~$: ./script.sh
/home/develop/trees
/bin:......:/home/develop/trees
~$: echo $BASE

~$: 

有什么问题吗?

1壳层是按照层次结构打开的。您可以使用. ./yourscript.sh来设置父壳层的变量。 - Janac Meena
3个回答

export 命令将变量赋值导出到运行 export 命令的 shell 进程的子进程中。您的命令行环境是脚本 shell 的“父级”,因此它看不到变量赋值。

您可以使用 .(或 source)bash 命令在当前 shell 环境中执行脚本命令,从而实现您想要的效果,例如:

source ./script.sh
echo "$BASE"

将产生
/home/develop/trees

在脚本中经常见到的source命令是bash对.的同义词,而.是POSIX标准的一部分(所以例如dash中有.,但没有source)。
. ./script.sh     # identical to "source ./script.sh"

. script.shsource script.sh会首先在PATH中查找script.sh,因此最好指定script.sh的路径。)

37你不需要使用export来传递变量给子shell,子shell是当前shell的副本,包括变量和函数等。导出的变量会被复制到从shell衍生出的新进程中,无论该进程是否是另一个shell。其次,.是用于执行脚本的POSIX命令。Bash添加了source作为更易读的同义词,但不能保证在sh中可用。最后,如果想避免意外情况,请使用. ./script而不是. script。参考链接:http://mywiki.wooledge.org/BashFAQ/060 - geirha
1请注意,如果您同时使用脚本和管道符号,则父环境无法访问脚本中的环境变量。例如,'source setit.sh' 是可以的,但 'source setit.sh |tee setit.log' 是不可以的。这令人惊讶且不直观。 - gaoithe
1刚刚以艰难的方式学到了一个教训,如果你习惯在所有脚本中使用set -euo pipefail,那么如果你在脚本中使用source命令,它将会在当前终端中设置这个选项,这意味着当终端接收到非零的退出代码(即失败)时,终端将会退出。这并不是最好的体验。你可以在脚本的末尾调用set +euo pipefail来关闭它,但仍然保持脚本失败时退出的安全性。 - Mike Harrison
是的。但它不会显示在命令> env中。 - Joeri

当你运行一个脚本时,它会在一个子shell中运行。变量只在该子shell的上下文中有效。在你的`.bashrc`或`.profile`中设置它们并详细了解一下variables and subshells。`export`语句的作用范围是向下的(当前shell及其所有子shell),而不是像你的示例中那样向上。
或者(如果你真的想让脚本影响当前shell的环境),可以这样运行它:
. ./script.sh

这会导致它在当前的shell中运行,但不会将变量传递到上层结构。

我经常想要轻松地设置一个环境变量。
以下是我在.bashrc中添加的内容,以实现这种便利。
defect() {
    if [ $1 ] && [ -z $2 ]
    then
        eval 'export DEFECT=$1'
        return 0
    else
        echo 'Usage: defect {number}'
        return 1
    fi
}