Linux传递环境变量

在Shell脚本中加入了类似export TEST=1的命令来添加环境变量,运行该脚本后发现当前的环境变量并没有发生变化,于是就去搜索了相关知识,并从中明确了Linux传递环境变量时的一些规则。

原问题

#!/bin/bash
export TEST=1

创建的测试脚本test.sh内容如上,脚本中的export TEST=1命令会添加一个名称为TEST且值为1的环境变量。
给脚本加上可执行权限并执行后使用echo $TEST,发现当前的环境变量并没有发生变化。
搜索之后了解到,对于一个Shell脚本通常有三种执行方式:

我使用的是第一种执行方式,问题就出在这里。
前两种执行方式本质上是相同的,都是从当前主进程中生成一个子进程,在子进程中执行脚本。因此子进程会继承主进程的环境变量,但子进程中环境变量的修改并不会影响到主进程。
第三种执行方式则是在当前主进程中执行脚本,其改动是直接对主进程的改动。

可以创建一个包含cd命令的测试脚本,按前两种方式执行后并不会改变当前目录,而第三种则会进入到对应的目录中,区别十分明显。

扩展问题

了解了执行脚本时环境变量的传递规则,不禁联想到susudo命令在使用时环境变量会如何确定。

其中sudo的环境变量传递方式是比较灵活的:

但在测试时发现,当前主进程中输入export TEST=1,添加环境变量后:

理论上sudo已经默认切换了环境变量,TEST值应该是未定义,那么为什么会输出1呢?
因为sudo echo $TEST整体作为一条命令,是先由当前Shell进程处理,再进而执行的。因此输入命令后,当前主进程先根据自身的TEST环境变量值为1,将命令处理为sudo echo 1后再执行,所以结果为1。
可以创建测试脚本test.sh,内容为:

#!/bin/bash
echo $TEST

然后在export TEST=1之后运行sh ./test.sh,结果会输出1,而运行sudo sh ./test.sh就没有结果输出了,与预期相符。