export和source

exportsource 是常用的Linux命令,有时一下子想不起来其用法,特总结此文。

环境

  • Ubuntu 22.04
  • zsh,bash

总结

若不想看全文,就只看总结:

  • export :变量能够传递到子shell中(以便调用其它脚本时,也能访问当前脚本所定义的变量)。
  • source :在当前shell而不是子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中的。

envset 查看环境变量:

  • env :全局环境变量,对当前shell和子shell都可见。
  • set :包括全局变量以及当前shell特有的变量(不传递到子shell中)。

要将父shell的变量传递到子shell,就需要使用 export 命令了。

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 命令了。

source

在当前shell中运行脚本。

➜  temp1016 source ./test1.sh 
Done

现在变量 aaa 就有值了:

➜  temp1016 echo $aaa        
1

source 命令常常用 . 代替。

注意:使用 source 命令时,要小心exit,因为exit的是当前shell。比如在 a.sh 中调用 b.shb.sh 有exit语句,如果是在 a.sh 中直接调用 b.sh ,没有问题,回exit到父shell,但如果在 a.sh 中通过source调用 b.sh ,则若b.sh 出错exit,就连同 a.sh 一起exit了。

一般我们使用source命令,是为了export变量。

完整例子

下面是一个简单而完整的例子。

main.shstep1.shstep2.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.

你可能感兴趣的:(Linux,linux,shell)