linux shell 5. Linux环境变量

5.1 什么是环境变量

bash shell用一个叫作环境变量(environment variable)的特性来存储有关shell会话和工作环境的信息(这也是它们被称作环境变量的原因)。这项特性允许你在内存中存储数据,以便程序或shell中运行的脚本能够轻松访问到它们。这也是存储持久数据的一种简便方法。
在bash shell中,环境变量分为两类:

  • 全局变量
  • 局部变量

5.1.1 全局环境变量

全局环境变量对于shell会话和所有生成的子shell都是可见的。局部变量则只对创建它们的shell可见。系统环境变量基本上都是使用全大写字母,以区别于普通用户的环境变量。
查看全局环境变量,使用env或者printenv命令:

$ printenv
HOSTNAME=server01.class.edu
SELINUX_ROLE_REQUESTED=
TERM=xterm
SHELL=/bin/bash
HISTSIZE=1000
[...]
HOME=/home/Christine
LOGNAME=Christine
[...]
G_BROKEN_FILENAMES=1
_=/usr/bin/printenv

注意:要显示个别环境变量的值,可以使用printenv命令,但是不要用env命令。

[mycms5@localhost ~]$ printenv HOME
/home/mycms5
[mycms5@localhost ~]$ env HOME
env: HOME: No such file or directory

也可以使用echo显示变量的值,这种情况下引用某个环境变量的时候,必须在变量前面加上一个美元符($)。

[mycms5@localhost ~]$ echo HOME
HOME
[mycms5@localhost ~]$ echo $HOME
/home/mycms5

注意上例输出的不同。在echo命令中,在变量名前加上$可不仅仅是要显示变量当前的值,它能够让变量作为命令行参数:

[mycms5@localhost ~]$ ls $HOME
chinahistory  lnmp  lnmp-mycms5.tar  lnmp.tar
[mycms5@localhost ~]$ ls /home/mycms5
chinahistory  lnmp  lnmp-mycms5.tar  lnmp.tar

下例可以看出,全局环境变量可用于进程的所有子shell:

[mycms5@localhost ~]$ bash 
[mycms5@localhost ~]$ bash
[mycms5@localhost ~]$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
mycms5    6394  6393  0 03:12 pts/0    00:00:00 -bash
mycms5    6860  6394  0 03:41 pts/0    00:00:00 bash
mycms5    6873  6860  1 03:42 pts/0    00:00:00 bash
mycms5    6886  6873  0 03:42 pts/0    00:00:00 ps -f
[mycms5@localhost ~]$ echo $HOME
/home/mycms5
[mycms5@localhost ~]$ exit
exit
[mycms5@localhost ~]$ exit
exit

5.1.2 局部环境变量

局部环境变量只能在定义它们的进程中可见,Linux系统也默认定义了标准的局部环境变量。不过你也可以定义自己的局部变量,如你所想,这些变量被称为用户定义局部变量。

查看局部环境变量的列表有点复杂。遗憾的是,在Linux系统并没有一个只显示局部环境变量的命令。set命令会显示为某个特定进程设置的所有环境变量,包括局部变量、全局变量以及用户定义变量。

$ set
BASH=/bin/bash
[...]
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
BASH_SOURCE=()
[...]
colors=/etc/DIR_COLORS
my_variable='Hello World'
[...]

可以看到,所有通过printenv命令能看到的全局环境变量都出现在了set命令的输出中。但在set命令的输出中还有其他一些环境变量,即局部环境变量和用户定义变量。

命令env、printenv和set之间的差异很细微。set命令会显示出全局变量、局部变量以及用户定义变量。它还会按照字母顺序对结果进行排序。env和printenv命令同set命令的区别在于前两个命令不会对变量排序,也不会输出局部变量和用户定义变量。在这种情况下,env和printenv的输出是重复的。不过env命令有一个printenv没有的功能,这使得它要更有用一些。

5.2 设置用户定义变量

5.2.1 设置局部用户定义变量

一旦启动了bash shell(或者执行一个shell脚本),就能创建在这个shell进程内可见的局部变量了。可以通过等号给环境变量赋值,值可以是数值或字符串。

[root@localhost ~]# echo $my_variable

[root@localhost ~]# my_variable=Hello
[root@localhost ~]# echo $my_variable
Hello
[root@localhost ~]# 

现在每次引用my_variable 环境变量的值,只要通过$my_variable引用即可。如果要给变量赋一个含有空格的字符串值,必须用单引号来界定字符串的首和尾。

[root@localhost ~]# my_variable=Hello World
-bash: World: command not found
[root@localhost ~]# my_variable='Hello World'
[root@localhost ~]# my_variable
-bash: my_variable: command not found
[root@localhost ~]# $my_variable
-bash: Hello: command not found
[root@localhost ~]# echo $my_variable
Hello World
[root@localhost ~]# 

注意,你定义的局部环境变量用的是小写字母,而到目前为止你所看到的系统环境变量都是大写字母。

所有的环境变量名均使用大写字母,这是bash shell的标准惯例。如果是你自己创建的局部变量或是shell脚本,请使用小写字母。变量名区分大小写。在涉及用户定义的局部变量时坚持使用小写字母,这能够避免重新定义系统环境变量可能带来的灾难。
特别注意的是:变量名、等号、值之间没有空格,这一点非常重要。若在赋值表达式中加上了空格,bash shell会把值当作一个单独的命令:

[root@localhost ~]# my_var = "1238383"
-bash: my_var: command not found

设置的局部环境变量,能在shell进程的任何地方使用,但是不可在生成的子shell中使用。

[root@localhost ~]# my_var="1238383"
[root@localhost ~]# bash 
[root@localhost ~]# echo $my_var
# 这里会有一个空行
[root@localhost ~]# exit
exit
[root@localhost ~]# echo $my_var
1238383
[root@localhost ~]# 

类似地,如果你在子进程中设置了一个局部变量,那么一旦你退出了子进程,那个局部环境变量就不可用。
当我们回到父shell时,子shell中设置的局部变量就不存在了。可以通过将局部的用户定义变量变成全局变量来改变这种情况。

6.2.2 设置全局环境变量

在设定全局环境变量的进程所创建的子进程中,该变量都是可见的。创建全局环境变量的方法是先创建一个局部环境变量,然后再把它导出到全局环境中。

这个过程通过export命令来完成,变量名前面不需要加$。

[mycms5@localhost ~]$ echo $my_var

[mycms5@localhost ~]$ my_var="I am Global now"
[mycms5@localhost ~]$ bash 
[mycms5@localhost ~]$ echo $my_var

[mycms5@localhost ~]$ exit
exit
[mycms5@localhost ~]$ echo $my_var
I am Global now
[mycms5@localhost ~]$ export my_var
[mycms5@localhost ~]$ bash 
[mycms5@localhost ~]$ echo $my_var
I am Global now
[mycms5@localhost ~]$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
mycms5   26283 26282  0 04:31 pts/0    00:00:00 -bash
mycms5   26354 26283  0 04:33 pts/0    00:00:00 bash
mycms5   26367 26354  0 04:33 pts/0    00:00:00 ps -f
[mycms5@localhost ~]$

修改子shell中全局环境变量并不会影响到父shell中该变量的值。

[mycms5@localhost ~]$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
mycms5   26283 26282  0 04:31 pts/0    00:00:00 -bash
mycms5   26354 26283  0 04:33 pts/0    00:00:00 bash
mycms5   26367 26354  0 04:33 pts/0    00:00:00 ps -f
[mycms5@localhost ~]$ my_var="null"
[mycms5@localhost ~]$ echo $my_var
null
[mycms5@localhost ~]$ exit
exit
[mycms5@localhost ~]$ echo $my_var
I am Global now
[mycms5@localhost ~]$ 

子shell甚至无法使用export命令改变父shell中全局环境变量的值。尽管子shell重新定义并导出了变量my_variable,但父shell中的my_variable变量依然保留着原先的值。

你可能感兴趣的:(linux shell 5. Linux环境变量)