Linux环境变量能帮你提升Linux shell体验。很多程序和脚本都通过环境变量来获取系统信息、存储临时数据和配置信息。在Linux系统上有很多地方可以设置环境变量,了解去哪里设置相应的环境变量很重要。
总结
命令 | 作用 | 示例 | 注释 |
---|---|---|---|
env | 查看全局环境变量 | env | |
printenv | 查看全局环境变量 | printenv HOME | 添加后缀可查看个别环境变量 |
echo | 查看全局环境变量 | echo $HOME | 添加$前缀 |
set | 显示所有环境变量 | set | |
1.什么是环境变量
bash shell用一个叫作环境变量(environment variable)的特性来存储有关shell会话和工作环境的信息(这也是它们被称作环境变量的原因)。这项特性允许你在内存中存储数据,以便程序或shell中运行的脚本能够轻松访问到它们。这也是存储持久数据的一种简便方法。
在bash shell中,环境变量分为两类:
全局变量
局部变量
尽管bash shell使用一致的专有环境变量,但不同的Linux发行版经常会添加其自有的环境变量。你在本章中看到的环境变量的例子可能会跟你安装的发行版中看到的结果略微不同。如果遇到本书未讲到的环境变量,可以查看你的Linux发行版上的文档。
1.全局环境变量
全局环境变量对于shell会话和所有生成的子shell都是可见的。局部变量则只对创建它们的shell可见。这让全局环境变量对那些所创建的子shell需要获取父shell信息的程序来说非常有用。
Linux系统在你开始bash会话时就设置了一些全局环境变量。系统环境变量基本上都是使用全大写字母,以区别于普通用户的环境变量。
要查看全局变量,可以使用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
系统为bash shell设置的全局环境变量数目众多,我们不得不在展示的时候进行删减。
其中有很多是在登录过程中设置的,另外,你的登录方式也会影响到所设置的环境变量。
要显示个别环境变量的值,可以使用printenv命令,但是不要用env命令。
$ printenv HOME
/home/Christine
$ env HOME
env: HOME: No such file or directory
也可以使用echo显示变量的值。在这种情况下引用某个环境变量的时候,必须在变量前面加上一个美元符($)。
$ echo $HOME
/home/Christine
在echo命令中,在变量名前加上$可不仅仅是要显示变量当前的值。它能够让变量作为命令行参数。
通俗来说就是可以作为快速命令使用
$ ls $HOME
$ ls /home/Christine
正如前面提到的,全局环境变量可用于进程的所有子shell。
$ bash
$
$ ps -f
UID PID PPID C STIME TTY TIME CMD
501 2017 2016 0 16:00 pts/0 00:00:00 -bash
501 2082 2017 0 16:08 pts/0 00:00:00 bash
501 2095 2082 0 16:08 pts/0 00:00:00 ps -f
$
$ echo $HOME
/home/Christine
$
$ exit
exit
$
在这个例子中,用bash命令生成一个子shell后,显示了HOME环境变量的当前值,这个值和父shell中的一模一样,都是/home/Chrisine。
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没有的功能,这使得它要更有用一些。
2.设置用户定义变量
可以在bash shell中直接设置自己的变量。本节将介绍怎样在交互式shell或shell脚本程序中创建自己的变量并引用它们。
1.设置局部用户定义变量
一旦启动了bash shell(或者执行一个shell脚本),就能创建在这个shell进程内可见的局部变量了。可以通过等号给环境变量赋值,值可以是数值或字符串。
$ echo $my_variable
$ my_variable=Hello
$
$ echo $my_variable
Hello
非常简单!现在每次引用my_variable 环境变量的值,只要通过$my_variable引用即可。
如果要给变量赋一个含有空格的字符串值,必须用单引号来界定字符串的首和尾。
$ my_variable=Hello World
-bash: World: command not found
$
$ my_variable="Hello World"
$
$ echo $my_variable
Hello World
$
没有单引号的话,bash shell会以为下一个词是另一个要执行的命令。注意,你定义的局部环境变量用的是小写字母,而到目前为止你所看到的系统环境变量都是大写字母。
所有的环境变量名均使用大写字母,这是bash shell的标准惯例。如果是你自己创建的局部变量或是shell脚本,请使用小写字母。变量名区分大小写。在涉及用户定义的局部变量时坚持使用小写字母,这能够避免重新定义系统环境变量可能带来的灾难。
记住,变量名、等号和值之间没有空格,这一点非常重要。如果在赋值表达式中加上了空格,bash shell就会把值当成一个单独的命令:
$ my_variable = "Hello World"
-bash: my_variable: command not found
$
设置了局部环境变量后,就能在shell进程的任何地方使用它了。但是,如果生成了另外一个shell,它在子shell中就不可用。
$ my_variable="Hello World"
$
$ bash
$
$ echo $my_variable
$ exit
exit
$
$ echo $my_variable
Hello World
$
在这个例子中生成了一个子shell。在子shell中无法使用用户定义变量my_variable。通过命令echo $my_variable所返回的空行就能够证明这一点。当你退出子shell并回到原来的shell时,这个局部环境变量依然可用。
类似地,如果你在子进程中设置了一个局部变量,那么一旦你退出了子进程,那个局部环境变量就不可用。
$ echo $my_child_variable
$ bash
$
$ my_child_variable="Hello Little World"
$
$ echo $my_child_variable
Hello Little World
$
$ exit
exit
$
$ echo $my_child_variable
$
当我们回到父shell时,子shell中设置的局部变量就不存在了。可以通过将局部的用户定义变量变成全局变量来改变这种情况。
2.设置全局环境变量
在设定全局环境变量的进程所创建的子进程中,该变量都是可见的。创建全局环境变量的方法是先创建一个局部环境变量,然后再把它导出到全局环境中。
这个过程通过export命令来完成,变量名前面不需要加$。
$ my_variable="I am Global now"
$
$ export my_variable
$
$ echo $my_variable
I am Global now
$
$ bash
$
$ echo $my_variable
I am Global now
$
$ exit
exit
$
$ echo $my_variable
I am Global now
$
在定义并导出局部环境变量my_variable后,bash命令启动了一个子shell。在这个子shell中能够正确的显示出变量my_variable的值。该变量能够保留住它的值是因为export命令使其变成了全局环境变量。
修改子shell中全局环境变量并不会影响到父shell中该变量的值。
$ my_variable="I am Global now"
$ export my_variable
$
$ echo $my_variable
I am Global now
$
$ bash
$
$ echo $my_variable
I am Global now
$
$ my_variable="Null"
$
$ echo $my_variable
Null
$
$ exit
exit
$
$ echo $my_variable
I am Global now
$
在定义并导出变量my_variable后,bash命令启动了一个子shell。在这个子shell中能够正确显示出全局环境变量my_variable的值。子shell随后改变了这个变量的值。但是这种改变仅在子shell中有效,并不会被反映到父shell中。
子shell甚至无法使用export命令改变父shell中全局环境变量的值。
$ my_variable="I am Global now"
$ export my_variable
$
$ echo $my_variable
I am Global now
$
$ bash
$
$ echo $my_variable
I am Global now
$
$ my_variable="Null"
$
$ export my_variable
$
$ echo $my_variable
Null
$
$ exit
exit
$
$ echo $my_variable
I am Global now
$
尽管子shell重新定义并导出了变量my_variable,但父shell中的my_variable变量依然保留着原先的值。