• Shell变量作用范围


    目录

    1、函数内的变量

    2、shell脚本内的变量

    3、进程内的变量

    4、进程间的变量

    5、终端间的变量

    6、用户间的变量

    总结


    本文内容同微信公众号【凡登】,关注不迷路,学习上高速,欢迎关注共同学习。

    什么是变量的作用范围? 变量在Shell脚本中的有效范围或可使用的范围, 什么是有效范围或可使用范围? 通过看一个示例看看

    1. # 定义一个变量
    2. [root@ ~]# name=joey
    3. # 编辑脚本hi.sh 内容为:echo "$name, hello",定义以脚本方式查看变量
    4. [root@ ~]# vim hi.sh
    5. echo "$name, hello"
    6. # 当前终端查看
    7. [root@ ~]# echo "$name, hello"
    8. joey, hello
    9. # 当前bash进程查看,能查看到变量
    10. [root@ ~]# source ./hi.sh
    11. joey, hello
    12. # bash子进程查看,不能查看到变量
    13. [root@ ~]# bash hi.sh
    14. , hello
    15. # 新启终端查看,不能查看到变量
    16. [root@ ~]# echo "$name, hello"
    17. , hello
    18. # 回到最初终端,导出变量后可以查看到,
    19. [root@ ~]# export name ; bash hi.sh
    20. joey, hello

    从上面可以看到,当前进程和终端可以访问当前定义的变量,而子进程和新启终端访问不到变量,

    当回到原终端通过export导出变量后,这时子进程可以访问到变量,然而新终仍然无法访问到变量,这是什么原因? 它就是本小节将要介绍的主题:变量的作用范围

    这里从简单到复杂,依次递进的方式将变量作用范围分为以下6种场景:函数内的变量shell脚本内的变量进程内的变量进程间的变量终端间的变量用户间的变量

    1、函数内的变量

    函数内的变量也就是局部变量。看下示例

    1. [root@ ~]# vi fun.sh
    2. #!/bin/bash
    3. function my_fun() {
    4. echo "--------函数开始--------------"
    5. local local_var1="我是函数局部变量" # 定义局部变量 var
    6. echo "执行函数:$local_var1 !" # 输出局部变量的值
    7. echo "--------函数结束--------------"
    8. }
    9. echo "执行函数前:$local_var1 !"
    10. my_fun # 执行函数
    11. echo "执行函数后:$local_var1 !"
    12. [root@ ~]# bash fun.sh
    13. 执行函数前: !
    14. --------函数开始--------------
    15. 执行函数:我是函数局部变量 !
    16. --------函数结束--------------
    17. 执行函数后: !

    小结:局部变量在函数中有效,超过函数范围就失效

    那可以在shell脚本中定义局部变量? 不可以。局部变量只能在函数中定义,

    如下图错误示例:

    1. [root@ ~]# vim fun_local_err.sh
    2. local v=123
    3. [root@ ~]# bash fun_local_err.sh
    4. fun_local_err.sh: line 1: local: can only be used in a function
    5. [root@ ~]# local vv=123
    6. bash: local: can only be used in a function

    2、shell脚本内的变量

    在shell脚本中定义的变量作用范围分为:局部变量和全局变量,局部变量在某个区域内有效,如函数块内。全局变量时整个shell脚本运行中有效,一旦脚本运行结束,全局变量就会失效。这里重点介绍全局变量

    1. [root@ ~]# vi fun.sh
    2. #!/bin/bash
    3. global_var1="我是脚本全局变量"
    4. function my_fun() {
    5. echo "--------函数开始--------------"
    6. global_var2="我是函数全局变量"
    7. echo "执行函数:$global_var2 !"
    8. echo "--------函数结束--------------"
    9. }
    10. echo "执行函数前:$global_var1 !"
    11. echo "执行函数前:$global_var2 !"
    12. my_fun # 执行函数
    13. echo "执行函数后:$global_var1 !"
    14. echo "执行函数后:$global_var2 !"
    15. [root@ ~]# bash fun.sh
    16. 执行函数前:我是脚本全局变量 !
    17. 执行函数前: !
    18. --------函数开始--------------
    19. 执行函数:我是函数全局变量 !
    20. --------函数结束--------------
    21. 执行函数后:我是脚本全局变量 !
    22. 执行函数后:我是函数全局变量 !

    全局变量作用域在shell脚本都有效,访问前必须先定义好变量。忽略是否在函数中定义,如例子所示,即使在函数中定义,当函数执行完后,全局变量仍有效。

    总结:局部变量只能在函数中定义和使用,且作用域在函数内。全局变量作用范围在整个脚本中,需要注意定义变量位置需在访问之前,且不受函数作用域范围的影响

    3、进程内的变量

    进程内变量描述的是bash进程中的变量。

    在介绍进程内变量之前,先回顾下脚本执行不同方式所带来的影响,

    bash xxx.sh 新起子进程执行xxx.sh , 脚本中行为只在子进程有效,对父进程环境没影响,

    source ./xxx.sh 在当前进程执行xxx.sh ,脚本行为对当前进程环境有影响。

    . xxx.sh 是source ./xxx.sh简写形式

    ./xxx.sh 新起子进程执行xxx.sh,

    4种不同执行方式和区别详情参见《shell简单认知》脚本的执行方式。回到本节主题进程变量的作用范围

    1. # 新建脚本hi.sh,内容为echo "$name, hello"
    2. [root@ ~]# echo 'echo "$name, hello"' > hi.sh
    3. # 当前进程新建变量name=123
    4. [root@ ~]# name=123
    5. [root@ ~]# echo $name
    6. 123
    7. # bash xxx.sh执行脚本,以子进程方式访问访问父进程name
    8. [root@ ~]# bash hi.sh
    9. , hello
    10. # source ./xxx.sh执行脚本,在当前进程访问name
    11. [root@ ~]# source hi.sh
    12. 123, hello
    13. # . xxx.sh 是 source ./xxx.sh的简写形式
    14. [root@ ~]# . hi.sh
    15. 123, hello
    16. # ./xx.sh子进程方式执行脚本
    17. [root@ ~]# chmod u+x hi.sh
    18. [root@ ~]# ./hi.sh
    19. , hello

    以上执行结果表明,同一进程变量访问不受限制,但子进程无法访问到父进程变量, 进程中的变量作用仅在当前进程的范围内有效,即进程变量也有自己的作用范围。

    问:如何跨进程访问,让子进程也可以访问父进程变量,实现进程间的变量共享?

    第4节《进程间的变量》

    4、进程间的变量

    进程间变量描述的是父子进程间变量。被export关键字修饰的变量,可以在进程间传递,也可以被子进程继承,从而在进程间实现变量共享。在第3节《进程内变量》例子中 bash hi.sh 访问不到name, 那么用export修饰name,再看执行结果

    1. # 导出当前变量
    2. [root@ ~]# export name
    3. # bash xxx.sh 方式访问父进程变量name
    4. [root@ ~]# bash hi.sh
    5. 123, hello
    6. # ./xxx.sh 方式访问父进程变量name
    7. [root@ ~]# ./hi.sh
    8. 123, hello

    执行结果看出,当用export修饰name变量后,就可以访问父进程name变量。

    export命令设置的变量是环境变量

    环境变量是在操作系统中用于存储各种配置信息的一种机制,通过设置环境变量,可以影响系统的行为和程序的运行。使用export命令,可以将一个变量从当前shell传递到子shell或其他进程中。当一个变量被导出后,它将成为子shell的环境变量,可以被其他命令和程序访问和使用

    5、终端间的变量

    在上一节学习了通过export修饰的变量可以在进程间传递,从而实现进程共享变量,那么能否在多个终端共享变量?先通过一个示例看看,在上述第4节《进程间的变量》例子中,新启一个终端,访问变量

    1. # 新启终端访问
    2. [root@ ~]#bash hi.sh
    3. , hello

    发现新启终端无法访问到上述通过export导出的环境变量,那么如何实现终端间的变量共享?

    1. [root@ ~]# vim ~/.bashrc
    2. export name=456
    3. # 使用source ~/.bashrc加载配置文件
    4. [root@ ~]# source ~/.bashrc
    5. # 访问可以看到原值123已经变为456
    6. [root@ ~]# bash hi.sh
    7. 456, hello
    8. # 新启终端访问,可以访问到最新值456
    9. [root@ ~]#bash hi.sh
    10. 456, hello

    说明:

    1、修改~/.bashrc,如果不使用source ~/.bashrc加载,那么访问的仍然是原来的值;

    当前终端立即访问,则需要通过source ~/.bashrc重新加载配置

    新终端会重新加载配置,无需再使用source ~/.bashrc加载配置文件

    2、写入~/.bashrc中的变量可以跨终端进行访问

    在bashrc中修改的值无法被立即访问,是因为修改的变量只在当前Shell进程中生效,而不会影响到父进程或其他子进程。当在bashrc中添加或修改环境变量时,这些变量只会对当前Shell及其子进程起作用,而不会影响其他已经运行的Shell或系统级的环境变量

    如果你希望在脚本中访问在bashrc中定义的变量,可以在脚本中通过source命令加载~/.bashrc文件。这样,脚本就会继承bashrc中定义的所有变量和配置。

    通过上述bashrc配置文件实现终端共享变量。

    6、用户间的变量

    在上一节学习了通过export修饰的变量可以在进程间传递,从而实现进程共享变量;通过~/.bashrc配置变量实现跨终端共享变量,那么能否在不同用户间共享变量?先通过一个示例看看

    1. # 创建新用户
    2. [root@ ~]# useradd joy
    3. [root@ ~]# passwd joy
    4. # 创建脚本访问name和NAME变量
    5. [root@ ~]# vi hi.sh
    6. echo "$name, hello"
    7. echo "$NAME, hello"
    8. echo "$_name, hello"
    9. # 将root脚本复制到用户joy家目录下
    10. [root@ ~]# cp /root/hi.sh /home/joy/
    11. # 定义name和NAME,_name变量
    12. [root@ ~]# name=123
    13. [root@ ~]# export NAME=456
    14. [root@ ~]# vim ~/.bashrc
    15. export _name=123456
    16. # 加载bashrc配置文件
    17. [root@ ~]# source ~/.bashrc
    18. # root用户下访问变量
    19. [root@ ~]# source ./hi.sh
    20. 123, hello
    21. 456, hello
    22. 123456, hello
    23. # 切换joy用户, 使用-表示用户登录加载所有配置文件
    24. [root@ ~]# su - joy
    25. # joy用户下执行脚本访问变量
    26. [joy@ ~]$ source ./hi.sh
    27. , hello
    28. , hello
    29. , hello

    上面演示,不管是shell全局变量或通过export修饰的环境变量,还是定义在~/.bashrc配置文件的变量,当切换到新用户后都访问不到。说明这些不具备跨用户共享,那么如何才能做到切换用户仍然可以访问变量?

    让我们在/etc/bashrc配置文件中新增变量,再观察一下

    1. # 新增变量
    2. [root@ ~]# vim /etc/bashrc
    3. export _NAME=123456789
    4. # 加载配置文件
    5. [root@ ~]# source /etc/bashrc
    6. # 在hi.sh后追加对_NAME的访问
    7. [root@ ~]# vim hi.sh
    8. echo "$_NAME, hello"
    9. # 移动到joy用户家目录下
    10. [root@ ~]# cp /root/hi.sh /home/joy/
    11. # root用户下访问
    12. [root@ ~]# source ./hi.sh
    13. 123, hello
    14. 456, hello
    15. 123456, hello
    16. 123456789, hello
    17. # 切换joy用户并登录
    18. [root@ ~]# su - joy
    19. # joy用户下访问变量,哎,这回可以访问_NAME变量,
    20. [joy@ ~]$ source ./hi.sh
    21. , hello
    22. , hello
    23. , hello
    24. 123456789, hello

    注:编辑/etc/bashrc需要root权限

    从上面结果可以看出当切换用户后,定义在/etc/bashrc下的变量仍可以访问,至此我们自定义的变量,实现了跨进程,跨终端,跨用户进行访问了。

    总结

    通过示例演示从函数->脚本->进程内->跨进程->跨终端->跨用户不同场景中变量表现,引出变量的作用范围,使用local修饰变量使变量的作用范围控制在函数内,在脚本中定义变量可以在函数中共享,通过使用export修饰变量使其能在进程间传递,实现进程间共享变量,扩大变量作用范围,另外修改配置文件~/.bashrc/etc/bashrc能使变量在多个终端和用户间共享,进一步扩大变量的作用范围,在日常工作中我们根据不同场景来限定变量范围,防止误伤。

    问:~/.bashrc /etc/bashrc配置文件是什么?为什么可以实现变量共享?还有没有类似配置文件?

    这些就是变量的配置文件,将在《变量配置文件》中讲解。

  • 相关阅读:
    Windows基础命令(目录文件、文本、网络操作)
    NodeJs实战-待办列表(4)-解决待办事项中文乱码问题
    C语言之文件操作(剩余部分)
    阿里云Redis之:配置程序接入阿里云Redis集群缓存数据(十七)
    51单片机 数码管操作
    [python]将多张图片合并为单个pdf文件
    Vue(调接口、组件、组件通信、生命周期)
    我在高职教STM32——GPIO入门之按键输入(2)
    Springboot+dubbo框架升级踩坑记
    Element UI + tree组件 + 面包屑 实现导航
  • 原文地址:https://blog.csdn.net/u013713832/article/details/134542890