• 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
    
    • 1
    • 2
    • 3
    • 4
    • 5

    可见,第二行的 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
    
    • 1
    • 2

    查看环境变量:

    ➜  ~ set | egrep 'xxx|yyy'
    xxx=123
    yyy=456
    
    ➜  ~ env | egrep 'xxx|yyy'
    yyy=456
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    可见, xxx 是自定义变量,而 yyy 是全局变量。

    接下来,打开一个子shell:

    ➜  ~ bash
    ding@ding-ubuntu:~$
    
    • 1
    • 2

    查看环境变量:

    ding@ding-ubuntu:~$ set | egrep 'xxx|yyy'
    yyy=456
    
    ding@ding-ubuntu:~$ env | egrep 'xxx|yyy'
    yyy=456
    
    • 1
    • 2
    • 3
    • 4
    • 5

    可见, yyy 被传递进来了,而 xxx 没有传递进来。

    注: export yyy=456 其实是下面的简写:

    ➜  ~ yyy=456
    ➜  ~ export yyy
    
    • 1
    • 2

    所以,其定义是“将用户自定义变量转变为全局变量”。

    如果有多个自定义变量,一般我们会放在脚本中定义,方便运行。比如,创建脚本 test1.sh 如下:

    #!/bin/bash
    
    export aaa=1
    export bbb=2
    export ccc=3
    
    echo "Done"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    现在,我们来运行脚本:

    ➜  temp1016 ./test1.sh
    Done
    
    • 1
    • 2

    接下来,我们来访问变量:

    ➜  temp1016 echo $aaa 
    
    ➜  temp1016 echo $bbb
    
    ➜  temp1016 echo $ccc
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    我们发现,变量并没有定义。这是怎么回事呢?

    前面讲了,通过 export 可以把父shell的变量传递到子shell。可是,并没有办法把子shell中的变量传回到父shell。

    当运行 ./test1.sh 时,实际上是在子shell中运行的,因为子shell中的变量无法传回到父shell,所以运行结束后,我们还是访问不了 aaa 变量。

    要解决这个问题,就需要 source 命令了。

    source

    在当前shell中运行脚本。

    ➜  temp1016 source ./test1.sh 
    Done
    
    • 1
    • 2

    现在变量 aaa 就有值了:

    ➜  temp1016 echo $aaa        
    1
    
    • 1
    • 2

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • step1.sh
    #!/bin/bash
    
    export name='zhangsan'
    export age=20
    
    • 1
    • 2
    • 3
    • 4
    • step2.sh
    #!/bin/bash
    
    echo "hello $name, you are $age years old."
    
    • 1
    • 2
    • 3

    运行结果如下:

    ➜  temp1016 ./main.sh 
    hello zhangsan, you are 20 years old.
    
    • 1
    • 2
  • 相关阅读:
    C++(List的模拟实现)
    数仓实践:数据仓库建设公共规范指南
    解决github加载过慢问题
    【案例 5-4】 字符串转换为二进制
    练习作业P1
    高性能面试八股文之编译流程&程序调度
    业务安全情报第22期 | 不法分子为何盗刷企业短信?
    Android—过渡按钮的简单实现
    VBM计算操作过程记录
    Java Reflection操作Classes的简介说明
  • 原文地址:https://blog.csdn.net/duke_ding2/article/details/133866677