什么是环境变量

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

在bash shell中,环境变量分为两类:

  1. 全局变量
  2. 局部变量

全局环境变量

全局环境变量对于shell会话和所有生成的子shell都是可见的。

Linux系统在你开始bash会话时就设置了一些全局环境变量系统环境变量基本上都是使用全大写字母,以区别于普通用户的环境变量。

要查看全局变量,可以使用env或printenv命令。

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

$ printenv HOME 
/home/Christine 
$
$ env HOME
  env: HOME: No such file or directory
$

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

$ echo $HOME 
/home/Christine 
$

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

局部环境变量

顾名思义,局部环境变量只能在定义它们的进程中可见。尽管它们是局部的,但是和全局环 境变量一样重要。事实上,Linux系统也默认定义了标准的局部环境变量。不过你也可以定义自己的局部变量,如你所想,这些变量被称为用户定义局部变量。

查看局部环境变量的列表有点复杂。遗憾的是,在Linux系统并没有一个只显示局部环境 变量的命令。

set命令会显示出某个进程的所有全局变量、局部变量以及用户定义变量。它还会按照字母顺序对结果进行排序。

env和printenv命令同set命令的区别在于前两个命令不会对变量排序,也不会输出局部变量和用户定义变量。在这种情况下,env和printenv的输出是重复的。不过env命令有一个printenv没有的功能,这使得它要更有用一些。

设置用户定义变量

设置局部用户定义变量

一旦启动了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就会把值当成一个单独的命令:

$ my_variable = "Hello World"
 -bash: my_variable: command not found 
$

设置了局部环境变量后,就能在shell进程的任何地方使用它了。但是,如果生成了另外一个 shell,它在子shell中就不可用。

设置全局环境变量

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

这个过程通过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中该变量的值。子shell甚至无法使用export命令改变父shell中全局环境变量的值。

删除环境变量

可以用unset命令完成这个操作。在unset命令中引用环境变量时,记住不要使用$。

$ echo $my_variable 
I am Global now
$
$ unset my_variable
$
$ echo $my_variable
$

在涉及环境变量名时,什么时候该使用$,什么时候不该使用$,实在让人摸不着头脑。 记住一点就行了:如果要用到变量,使用$;如果要操作变量,不使用$。这条规则的一 个例外就是使用printenv显示某个变量的值。

在处理全局环境变量时,事情就有点棘手了。如果你是在子进程中删除了一个全局环境变量, 这只对子进程有效。该全局环境变量在父进程中依然可用。

默认的shell环境变量

默认情况下,bash shell会用一些特定的环境变量来定义系统环境。这些变量在你的Linux系 统上都已经设置好了,只管放心使用。bash shell源自当初的Unix Bourne shell,因此也保留了Unix Bourne shell里定义的那些环境变量。

除了默认的Bourne的环境变量,bash shell还提供一些自有的变量,如表6-2所示。

你可能已经注意到,不是所有的默认环境变量都会在运行set命令时列出。尽管这些都是默 认环境变量,但并不是每一个都必须有一个值。

设置PATH环境变量

当你在shell命令行界面中输入一个外部命令时,shell必须搜索系统来找到对应 的程序。PATH环境变量定义了用于进行命令和程序查找的目录。

如果命令或者程序的位置没有包括在PATH变量中,那么如果不使用绝对路径的话,shell是没 法找到的。

解决的 办法是保证PATH环境变量包含了所有存放应用程序的目录。可以把新的搜索目录添加到现有的PATH环境变量中,无需从头定义。PATH中各个目录之间是用冒号分隔的。你只需引用原来的PATH值,然后再给这个字符串添加新目录就行了。

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin: /sbin:/bin:/usr/games:/usr/local/games
$
$ PATH=$PATH:/home/christine/Scripts
$
$ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/
     games:/usr/local/games:/home/christine/Scripts
$
$ myprog
The factorial of 5 is 120. 
$

将目录加到PATH环境变量之后,你现在就可以在虚拟目录结构中的任何位置执行程序。

如果希望子shell也能找到你的程序的位置,一定要记得把修改后的PATH环境变量导出.

程序员通常的办法是将单点符也加入PATH环境变量。

$ PATH=$PATH:.
$
$ cd /home/christine/Old_Scripts 
$
$ myprog2
The factorial of 6 is 720
$

对PATH变量的修改只能持续到退出或重启系统。这种效果并不能一直持续。

补充内容

1. 获得宇符串长度

可以用下面的方法获得变量值的长度:

length-${#var}

例如:

$ var=12345678901234567890
$ echo ${#var}
20

length就是字符串所包含的字符数。

识别当前的shell版本

可以用下面的方法获知当前使用的是哪种shell:

echo $SHELL

也可以用

echo $0

例如:

$ echo $SHELL
/bin/bash
$ echo $0
bash

检查是否为超级用户

UID是一个重要的环境变量,可以用于检査当前脚本是以超级用户还是以普通用户的身份运行的。例如:

if [ $UID -ne 0 ]; then
echo Non root user. Please run as root.
else
echo "Root user"
fi

root用户的uid是0。

修改Bash提示字符串(usemame01iostnaine:~$)