Linux shell 学习笔记(4)— linux 环境变量(全局变量、局部变量及变量持久化)

1. 环境变量概念及分类

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

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

  • 全局变量
  • 局部变量
1.1 全局环境变量

全局环境变量对于 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

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

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

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

$ echo $HOME
/home/Christine
$
1.2 局部环境变量

局部环境变量只能在定义它们的进程中可见,事实上,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'
[...]
$

注意:命令 env、printenv 和 set 之间的差异很细微。set 命令会显示出全局变量、局部变量以及用户定义变量。它还会按照字母顺序对结果进行排序。env 和 printenv 命令同 set 命令的区别在于前两个命令不会对变量排序,也不会输出局部变量和用户定义变量。

2. 设置自定义变量

2.1 设置局部用户自定义变量

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

$ echo $my_variable
$ my_variable=Hello
$
$ echo $my_variable
Hello

如果要给变量赋一个含有空格的字符串值,必须用单引号来界定字符串的首和尾。

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

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

注意:所有的环境变量名均使用大写字母,这是 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 时,这个局部环境变量依然可用。

类似地,如果你在子进程中设置了一个局部变量,那么一旦你退出了子进程,那个局部环境变量就不可用。

2.2 设置全局环境变量

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

  1. 这个过程通过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
    $
    

  2. 修改子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
    $
    

  3. 子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
    $
    

3. 删除环境变量

既然可以创建新的环境变量,自然也能删除已经存在的环境变量。可以用 unset 命令完成这个操作。在 unset 命令中引用环境变量时,记住不要使用 $。

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

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

$ my_variable="I am Global now"
$
$ export my_variable
$
$ echo $my_variable
I am Global now
$
$ bash
$
$ echo $my_variable
I am Global now
$
$ unset my_variable
$
$ echo $my_variable
$ exit
exit
$
$ echo $my_variable
I am Global now
$

和修改变量一样,在子 shell 中删除全局变量后,你无法将效果反映到父 shell 中。

4. 设置 PATH 环境变量

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

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:
/sbin:/bin:/usr/games:/usr/local/games
$

输出中显示了有 8 个可供 shell 用来查找命令和程序。PATH 中的目录使用冒号分隔。
如果命令或者程序的位置没有包括在 PATH 变量中,那么如果不使用绝对路径的话,shell 是没法找到的。如果 shell 找不到指定的命令或程序,它会产生一个错误信息:

$ myprog
-bash: myprog: command not found
$

问题是,应用程序放置可执行文件的目录常常不在 PATH 环境变量所包含的目录中。解决的办法是保证 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 变量的修改只能持续到退出或重启系统。这种效果并不能一直持续。

5. 环境变量持久化

对全局环境变量来说(Linux系统中所有用户都需要使用的变量),可能更倾向于将新的或修改过的变量设置放在 /etc/profile 文件中,但这可不是什么好主意。如果你升级了所用的发行版,这个文件也会跟着更新,那你所有定制过的变量设置可就都没有了。

最好是在 /etc/profile.d目录中创建一个以.sh 结尾的文件。把所有新的或修改过的全局环境变量设置放在这个文件中。

在大多数发行版中,存储个人用户永久性 bash shell 变量的地方是 $HOME/.bashrc 文件。这一点适用于所有类型的 shell 进程。但如果设置了 BASH_ENV变量,那么记住,除非它指向的是
$HOME/.bashrc,否则你应该将非交互式 shell 的用户变量放在别的地方。

6. 数组变量

环境变量有一个很酷的特性就是,它们可作为数组使用。

  1. 要给某个环境变量设置多个值,可以把值放在括号里,值与值之间用空格分隔

    $ mytest=(one two three four five)
    $
    
  2. 要引用一个单独的数组元素,就必须用代表它在数组中位置的数值索引值。索引值要用方括号括起来

    $ echo ${mytest[2]}
    three
    $
    
  3. 要显示整个数组变量,可用星号作为通配符放在索引值的位置

    $ echo ${mytest[*]}
    one two three four five
    $
    
  4. 也可以改变某个索引值位置的值

    $ mytest[2]=seven
    $
    $ echo ${mytest[*]}
    one two seven four five
    $
    
  5. 甚至能用 unset 命令删除数组中的某个值,但是要小心,这可能会有点复杂

    $ unset mytest[2]
    $
    $ echo ${mytest[*]}
    one two four five
    $
    $ echo ${mytest[2]}
    $ echo ${mytest[3]}
    four
    $
    

    这个例子用 unset 命令删除在索引值为 2 的位置上的值。显示整个数组时,看起来像是索引里面已经没这个索引了。但当专门显示索引值为 2 的位置上的值时,就能看到这个位置是空的。

  6. 可以在 unset 命令后跟上数组名来删除整个数组

    $ unset mytest
    $
    $ echo ${mytest[*]}
    $
    
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值