shell运行环境之环境变量

 |   

在 Windows 系统中,我们经常需要设置环境变量,特别是安装完 Java JDK 之后。而在 Linux 里面也是需要对一些环境变量进行设置,比如 PATH (执行文件的路径),http_proxy(http 代理)等。本文主要介绍三种环境变量–临时变量,用户变量和系统变量,并对其作用的先后做一些验证。

简介

环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件夹位置和系统文件夹位置等。它相当于给系统或用户应用程序设置的一些参数,具体起什么作用这和具体的环境变量相关。

在 Windows 系统里面,经常会遇到 设置环境变量的问题,特别是安装完 Java JDK 之后。我们很少在黑漆漆的命令行窗口中执行命令set path=%path%;D:\jdk\bin,因为这样设置的变量是临时环境变量,它只能在这个命令窗口中被识别,知道 java 命令在 D:\jdk\bin 目录里,但当重新打开一个命令窗口(Shell 外壳)后新窗口将无法识别。也就是说该 PATH 只对执行那个命令的 Shell 有效。还有两种方法是设置用户变量或系统变量。二者的区别就在于系统变量对所有用户有效,而用户变量只对当前用户有效。经试验,win8系统中二者都无需重启就可以起作用。

Linux 环境变量设置

其实,linux里面对环境变量的设置和windows是共通的。它也有三种方式

  • 临时变量
    在 Shell 外壳中执行命令PATH=$PATH':/home/hjy/program/jdk/bin',同样 Java 命令只能在当前窗口中识别,重开一个外壳 java 命令将无效。
  • 用户变量
    Linux 里面关于用户变量的设置是在两个文件中,一个是 /etc/profile,另一个是 ~/.profile。profile 是配置的意思,是某个用户唯一用来设置环境变量的地方。针对不同的用户习惯,使用不同的 Shell(像bash,sh,zsh等),针对不同的功能或不同的应用,加载不同的环境变量文件。
  • 系统变量
    Linux 里面关于系统变量的设置是在 /etc/environment 文件中。该环境变量的设置不需要加 export,直接赋值即可。

验证作用域

易知临时变量的作用域只在当前的终端中,出了当前终端将失效。而对于用户变量和系统变量,我们这里做两个小的试验,其中一个是 网上的,关键是讲解中又是疑问又是否定的,没搞明白作者啥意思,所以这里亲自验证一下。

图形界面登录

经试验发现,自己的电脑环境和网上博主还是有些区别的。主要在 本地化语言环境设定上的区别,在安装好中文和英文的语言包后,系统的本地语言环境如图:

ori_locale
但是由这篇博文– locale的设定中LANG、LC_ALL、LANGUAGE环境变量的区别知道,LC_ALL > LC_* >LANG,所以在本机上配置 LANG 将会被 LC_* 所取代,而导致无论怎么设置都是英文环境。所以实际实验是设定 LC_ALL 变量。

  • 试验步骤
    1. export LC_ALL=zh_CN.UTF-8 加入 /etc/profile,退出系统重新登录,登录界面和 locale 变量如下图所示:
      eprofile

      pro_locale
    2. 删除 /etc/profile 中的 export LC_ALL=zh_CN.UTF-8,并将其加入到 /etc/envirionment,退出系统重新登录,登录界面和locale变量如下图所示:
      environment

      env_locale
  • 结论: 在登录界面时(还没有用户登录系统),系统执行了 /etc/environment,仅此而已。而对于是否执行 /etc/profile 以及这两个文件谁先谁后的问题无法得出结论。对于这个问题,后面会做一下讨论。

结论: 用户登录系统前,即刚进入登录界面,此时 /etc/environment 已经被执行。

用户登录后进入shell后

  • 试验步骤

    1. 在/etc/profile文件中加入如下变量:

      1export eprofile='I am in /etc/profile'
      2export epro_env='I am in /etc/profile'
      3export epro_pro='I am in /etc/profile'
      
    2. 在/etc/environment文件中加入如下变量:

      1environment='I am in /etc/environment'
      2epro_env='I am in /etc/environment'
      3env_pro='I am in /etc/environment'
      
    3. 在~/.profile文件中加入如下变量:

      1export profile='I am in ~/.profile'
      2export epro_pro='I am in ~/.profile'
      3export env_pro='I am in ~/.profile'
      
    4. 重启系统后查看 profile, environment, homepro, pro_env, pro_env_pro这五个变量的值,结果如下图所示:

      login

  • 结论:

    1. 三个环境配置文件都被执行了
      变量 environment, eprofile, profile 都有值
    2. /etc/environment 优先于 /etc/profile
      变量 epro_env 是 /etc/profile 里面的值,结合第一个结论,可得 /etc/environment 优先于 /etc/profile
    3. /etc/profile 优先于 ~/.profile
      变量 epro_pro 是 ~/.profile 里面的值,结合第一个结论,可得 /etc/profile 优先于 ~/.profile

结论: 用户登录系统打开shell后,/etc/environment,/etc/profile和~/.profile执行顺序是: /etc/environment => /etc/profile => ~/.profile

问题讨论

  1. 关于第一个试验中只能得出 /etc/environment 在登录界面前将被执行,而对于是否执行 /etc/profile 以及这两个文件谁先谁后的问题无法得出结论。
    从两幅登录界面发现在 /etc/environment 设定的 LC_ALL 起作用了,但是 /etc/profile 中的不起作用可能是被后面的覆盖掉,也有可能该文件还没有被执行,至于后面 locale 变量的比较,是在我们登录进系统后打开 Shell 后看到的。所以无法判定在登录界面之前/etc/profile是否被执行,更不谈谁先谁后。 个人倾向的解释是登录界面之前只是执行 /etc/environment,不会执行 /etc/profile,当输入用户和密码后才会以登录模式进入系统,此时 /etc/profile 和 ~/.profile 才会被执行。

参考文献

  1. 环境变量定义
  2. 如何设置或更改PATH系统变量
  3. etc/profile和/etc/environment的比较
  4. 本地化环境变量LANG、LC_ALL、LANGUAGE的区别
  5. wiki locale
技术茶话会
< 前一篇 后一篇 >