export
和 source
是常用的Linux命令,有时一下子想不起来其用法,特总结此文。
若不想看全文,就只看总结:
export
:变量能够传递到子shell中(以便调用其它脚本时,也能访问当前脚本所定义的变量)。source
:在当前shell而不是子shell中运行脚本(常用于定义变量,因为子shell的变量无法传回父shell)。在父shell中可以运行子shell。比如,在zsh中可以打开一个bash:
ding@ding-ubuntu:~$ ps -ef | egrep "zsh|bash"
......
ding 10858 2535 0 19:11 pts/1 00:00:00 /usr/bin/zsh
ding 10970 10858 0 19:13 pts/1 00:00:00 bash
ding 12000 10970 0 19:23 pts/1 00:00:00 grep -E --color=auto zsh|bash
可见,第二行的 bash
,其PPID(parent PID)10858,正是第一行zsh的PID。我们称此bash为zsh的子shell。
在一个脚本中调用其它脚本,默认也是在其子shell中运行的。
当我们在 a.sh
中调用 b.sh
时,一般我们也会想要把在 a.sh
中设置的变量传递到 b.sh
中。但是默认情况下,在父shell中定义的变量,是不会传递到子shell中的。
用 env
和 set
查看环境变量:
env
:全局环境变量,对当前shell和子shell都可见。set
:包括全局变量以及当前shell特有的变量(不传递到子shell中)。要将父shell的变量传递到子shell,就需要使用 export
命令了。
export
命令将用户自定义变量转变为全局变量,也就是说,会传递到子shell中。
直接看例子。首先定义变量 xxx
和 全局变量 yyy
:
➜ ~ xxx=123
➜ ~ export yyy=456
查看环境变量:
➜ ~ set | egrep 'xxx|yyy'
xxx=123
yyy=456
➜ ~ env | egrep 'xxx|yyy'
yyy=456
可见, xxx
是自定义变量,而 yyy
是全局变量。
接下来,打开一个子shell:
➜ ~ bash
ding@ding-ubuntu:~$
查看环境变量:
ding@ding-ubuntu:~$ set | egrep 'xxx|yyy'
yyy=456
ding@ding-ubuntu:~$ env | egrep 'xxx|yyy'
yyy=456
可见, yyy
被传递进来了,而 xxx
没有传递进来。
注: export yyy=456
其实是下面的简写:
➜ ~ yyy=456
➜ ~ export yyy
所以,其定义是“将用户自定义变量转变为全局变量”。
如果有多个自定义变量,一般我们会放在脚本中定义,方便运行。比如,创建脚本 test1.sh
如下:
#!/bin/bash
export aaa=1
export bbb=2
export ccc=3
echo "Done"
现在,我们来运行脚本:
➜ temp1016 ./test1.sh
Done
接下来,我们来访问变量:
➜ temp1016 echo $aaa
➜ temp1016 echo $bbb
➜ temp1016 echo $ccc
我们发现,变量并没有定义。这是怎么回事呢?
前面讲了,通过 export
可以把父shell的变量传递到子shell。可是,并没有办法把子shell中的变量传回到父shell。
当运行 ./test1.sh
时,实际上是在子shell中运行的,因为子shell中的变量无法传回到父shell,所以运行结束后,我们还是访问不了 aaa
变量。
要解决这个问题,就需要 source
命令了。
在当前shell中运行脚本。
➜ temp1016 source ./test1.sh
Done
现在变量 aaa
就有值了:
➜ temp1016 echo $aaa
1
source
命令常常用 .
代替。
注意:使用 source
命令时,要小心exit,因为exit的是当前shell。比如在 a.sh
中调用 b.sh
, b.sh
有exit语句,如果是在 a.sh
中直接调用 b.sh
,没有问题,回exit到父shell,但如果在 a.sh
中通过source调用 b.sh
,则若b.sh
出错exit,就连同 a.sh
一起exit了。
一般我们使用source命令,是为了export变量。
下面是一个简单而完整的例子。
main.sh
、 step1.sh
、 step2.sh
内容如下:
main.sh
:#!/bin/bash
. ./step1.sh
./step2.sh
step1.sh
:#!/bin/bash
export name='zhangsan'
export age=20
step2.sh
:#!/bin/bash
echo "hello $name, you are $age years old."
运行结果如下:
➜ temp1016 ./main.sh
hello zhangsan, you are 20 years old.