shell 环境变量的作用域

概述:shell变量的作用域,就是shell变量的有效范围,在不同的作用域中,同名的变量不会相互干涉,就比如:A班级中有个叫小明的同学,B班级中也有一个叫小明的同学,由于他们不在同一个班级中,所以当在班级中叫到小明的名字的时候,不会造成混乱。

shell变量的作用域分为3种:

  • 局部变量(local variable):只能在函数内部使用,需要使用local命令(局部变量只能在函数内部使用,但在函数内使用的变量不全是局部变量)
  • 全局变量(global varlable):在当前的shell 进程中使用的变量,叫做全局变量
  • 环境变量(environment variable):可以在子进程中使用。

1. shell 局部变量

在shell函数中定义的变量默认也为全局变量,需要使用local命令来声明局部变量,观查下面两段代码演示说明:

[root@docker /variable]# vim function_1.sh
#!/bin/bash
#定义函数
function fun(){

        a=100
}
#调用函数
fun
#输出函数内的变量值
echo    $a
"function.sh" 12L, 69C 已写入
[root@docker /variable]# sh function_1.sh
100

看输出结果,变量a是在函数内部定义,但是在函数外部也可以得到变量a的值,证明它是一个全局变量。

[root@docker /variable]# vim function_2.sh
#!/bin/bash
#定义函数
function fun(){

   local a=50
}
fun
echo    $a
"function_2.sh" 12L, 77C 已写入
[root@docker /variable]# sh function_2.sh

[root@docker /variable]#

输出结果为空,说明变量a在函数外部无效,是一个局部变量,仔细看上面的脚本,使用local用来声明局部变量。


2. shell 全局变量

所谓全局变量,就是指变量在当前shell进程中都有效,每个shell进程都有自己的作用域,彼此之间互不影响,在shell脚本中定义的变量,默认就是全局变量.

打开2个shell窗口,在其中一个窗口定义一个变量a并赋值100,然后打印a的值,发现输出100;在另一个shell窗口同样打印a的值,发现输出结构为空。这说明全局变量a仅仅在定义它的shell进程中有效,对新的shell进程无效。如图所示

shell全局变量说明.png

**需要强调的是,全局变量的作用范围是当前的进程,打开一个 Shell 窗口就创建了一个 Shell 进程,每个 Shell 进程都是独立的,拥有不同的进程 ID,执行shell脚本时也会生成一个进程,也会有用一个进程ID,所以想要使全局变量在这些脚本文件中都有效需要使用source 命令或. ./a.sh 的方法(source a.sh 命令表示在当前进程执行shell脚本,和使用. ./a.sh 、. a.sh 效果相同) 演示如下: **

[root@docker /variable]# a=100
[root@docker /variable]# cat a.sh
#!/bin/bash
echo $a
b=200
[root@docker /variable]# cat b.sh
#!/bin/bash
echo $b
[root@docker /variable]# source a.sh
100
[root@docker /variable]# source b.sh
200
[root@docker /variable]#

3. shell 环境变量

全局变量旨在当前的shll进程中有效,对其他的进程和子进程都无效,如果使用==export==命令将全局变量导出,那么他就在所有子进程中都有效了,这称之为“环境变量”。

环境变量被创建时所处的进程称为父进程,如果在父进程中在创建一个细腻的进程来执行shell命令,那么这个新的进程被称作shell子进程,当shell子进程产生式,它会继承父进程的环境变量为自己所用,所以说环境变量可从父进程传给子进程,不难理解,环境变量还可以传递给孙进程。

创建shell子进程最简单的方式就是运行bash命令(如图所示)


进入shell的子进程.png
[root@docker ~]$ a=22       #定义一个全局变量
[root@docker ~]$ echo $a    #在当前Shell中输出a,成功
22
[root@docker ~]$ bash       #进入Shell子进程
[root@docker ~]$ echo $a    #在子进程中输出a,失败

[root@docker ~]$ exit       #退出Shell子进程,返回上一级Shell
exit
[root@docker ~]$ export a   #将a导出为环境变量
[root@docker ~]$ bash       #重新进入Shell子进程
[root@docker ~]$ echo $a    #在子进程中再次输出a,成功
22
[root@docker ~]$ exit       #退出Shell子进程
exit
[root@docker ~]$ exit       #退出父进程,结束整个Shell会话

可以发现,默认情况下,a 在 Shell 子进程中是无效的;使用 export 将 a 导出为环境变量后,在子进程中就可以使用了。

我们一直强调的是环境变量在 Shell 子进程中有效,并没有说它在所有的 Shell 进程中都有效;如果你通过终端创建了一个新的 Shell 窗口,那它就不是当前 Shell 的子进程,环境变量对这个新的 Shell 进程仍然是无效的。

环境变量也是临时的

通过 export 导出的环境变量只对当前 Shell 进程以及所有的子进程有效,如果最顶层的父进程被关闭了,那么环境变量也就随之消失了,其它的进程也就无法使用了,所以说环境变量也是临时的。


4. shell 配置文件(脚本)加载

无论是否是交互式、是否是登录式,Bash shell 在启动时总要配置其运行环境,例如初始化环境变量、设置命令提示符、指定系统命令路径等。这过程都是通过加载一系列的配置文件完成的,这些配置文件其实就是脚本文件。

Bash 官方文档说:如果是登录式的 Shell,首先会读取和执行 /etc/profile,这是所有用户的全局配置文件,接着会到用户主目录中寻找 /.bash_profile、/.bash_login 或者 ~/.profile,它们都是用户个人的配置文件。

Bash shell 有关的配置文件主要有 /etc/profile、/.bash_profile、/.bash_login、/.profile、/.bashrc、/etc/bashrc、/etc/profile.d/*.sh,不同的启动方式会加载不同的配置文件。

全局配置

/etc/profile此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行。并从 /etc/profile.d 目录的配置文件中收集 shell 的设置。如果你有对 /etc/profile 有修改的话必须得 source 一下你的修改才会生效,此修改对每个用户都生效。

/etc/bashrc为每一个运行 bash shell 的用户执行此文件。当 bash shell 被打开时,该文件被读取。如果你想对所有的使用 bash 的用户修改某个配置并在以后打开的 bash 都生效的话可以修改这个文件,修改这个文件不用重启,重新打开一个 bash 即可生效。

用户配置

~/.bash_profile每个用户都可使用该文件输入专用于自己使用的 shell 信息,当用户登录时,该文件仅仅执行一次!默认情况下,它设置一些环境变量,执行用户的~/ .bashrc 文件。 此文件类似于 /etc/profile,也是需要需要 source 才会生效,/etc/profile 对所有用户生效,~/.bash_profile 只对当前用户生效。

~/.profile(由Bourne Shell和Korn Shell使用)和.login(由C Shell使用)两个文件是.bash_profile的同义词,==目的是为了兼容其它Shell==。

如下.bash_profile系统默认配置:

[root@docker ~]# cat ~/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH
[root@docker ~]#

~/.bashrc该文件包含专用于你的 bash shell 的 bash 信息,当登录时以及每次打开新的 shell 时,该文件被读取。(每个用户都有一个 ~/.bashrc 文件,在用户目录下) 此文件类似于 /etc/bashrc,不需要重启就可以生效,重新打开一个 bash 即可生效,/etc/bashrc 对所有用户新打开的 bash 都生效,但 ~/.bashrc 只对当前用户新打开的 bash 生效。
~/.bashrc文件会在bash shell调用另一个bash shell时读取,也就是在shell中再键入bash命令启动一个新shell时就会去读该文件。这样可有效分离登录和子shell所需的环境。但一般 来说都会在/.bash_profile里调用/.bashrc脚本以便统一配置用户环境。


5. 登录式shell和非登录式shell区别

  • 登录式shell

交互式登录:(清除掉所有变量,通过文件重新读入)

1.直接通过终端输入账号密码登录

2.使用“su - username”切换的用户

执行顺序:(影响该shell的配置文件)/etc/profile --> /etc/profile.d/.sh --> ~/.bash_profile–> ~/.bashrc–> /etc/bashrc

  • 非登录式shell

如果以非登录的方式启动 Shell,那么就不会读取以上所说的配置文件,而是直接读取 ~/.bashrc;~/.bashrc 文件还会嵌套加载 /etc/bashrc

1.su username

2.图形界面下打开的终端

3.执行脚本 (当我们执行脚本的时候.我们就已经进入到了一个子shell)

4.任何其它的bash实例
执行顺序:(影响该shell的配置文件)~/.bashrc–> /etc/bashrc–> /etc/profile.d/.sh

6.检查系统环境变量的命令

  • set 输出所有变量,包括全局变量、局部变量
  • env 只显示痊愈变量
  • declare 输出所有的变量,如同 set
  • export 只显示和设置环境变量值

7.删除环境变量

  • unset 变量名 ,删除变量或函数。

你可能感兴趣的:(shell 环境变量的作用域)