Linux传递环境变量
2018-07-28 ArchLinux在Shell脚本中加入了类似
export TEST=1
的命令来添加环境变量,运行该脚本后发现当前的环境变量并没有发生变化,于是就去搜索了相关知识,并从中明确了Linux传递环境变量时的一些规则。
原问题
#!/bin/bash
export TEST=1
创建的测试脚本test.sh
内容如上,脚本中的export TEST=1
命令会添加一个名称为TEST且值为1的环境变量。
给脚本加上可执行权限并执行后使用echo $TEST
,发现当前的环境变量并没有发生变化。
搜索之后了解到,对于一个Shell脚本通常有三种执行方式:
- 直接执行:先给脚本加上可执行权限,再直接执行脚本。
$ chmod +x test.sh
$ ./test.sh
- 使用
sh
命令:脚本文件不需要可执行权限,使用sh
命令执行脚本。
$ sh ./test.sh
,类似的,也可以使用bash
命令通过$ bash ./test.sh
执行。 - 使用
source
命令:脚本文件不需要可执行权限,使用source
命令执行脚本。
$ source ./test.sh
,也可简写为$ . ./test.sh
。
我使用的是第一种执行方式,问题就出在这里。
前两种执行方式本质上是相同的,都是从当前主进程中生成一个子进程,在子进程中执行脚本。因此子进程会继承主进程的环境变量,但子进程中环境变量的修改并不会影响到主进程。
第三种执行方式则是在当前主进程中执行脚本,其改动是直接对主进程的改动。
可以创建一个包含cd
命令的测试脚本,按前两种方式执行后并不会改变当前目录,而第三种则会进入到对应的目录中,区别十分明显。
扩展问题
了解了执行脚本时环境变量的传递规则,不禁联想到su
,sudo
命令在使用时环境变量会如何确定。
su
只切换到root用户,环境变量保持不变。su -
切换到root用户,环境变量也重置为root用户的环境变量。sudo
切换到root用户,环境变量也重置为root用户的环境变量。sudo -E
sudo提供额外选项-E,只切换到root用户,环境变量保持不变。
其中sudo的环境变量传递方式是比较灵活的:
- 默认不传递,即切换用户的同时也切换环境变量。
- 可以用-E选项开启传递,只切换用户,之前的环境变量会保留。
- 也可以修改配置文件,设定切换用户时只传递部分环境变量。
但在测试时发现,当前主进程中输入export TEST=1
,添加环境变量后:
$ echo $TEST
,结果会输出1。$ sudo echo $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
就没有结果输出了,与预期相符。