从环境变量的作用范围来说,Linux下的环境变量分为系统环境变量和用户环境变量,系统环境变量在 /etc/profile 文件或/etc/profile.d 目录下配置,对该系统中所有用户都生效;用户环境变量在 ~/.bash_profile文件中配置,只对用户自己生效。

从环境变量的生命周期来说,Linux下的环境变量分为永久环境变量和临时环境变量,修改/etc/profile~/.bash_profile等相关配置文件并让变量生效的是永久环境变量,用户利用 export 命令在当前终端下声明环境变量,关闭Shell终端就失效的环境变量是临时环境变量。

根据自己对环境变量配置的需求场景,选择一种最好的方式来配置环境变量,一般应用场景下,全局变量配置于 /etc/profile.d 目录下是最佳的实践方式,诸如JDK、nodeJs等用在我们程序开发环境配置大多都作为永久环境变量;临时变量常用在一些比较特殊的.sh脚本中临时使用。

/etc/profile 文件

当一个用户登录Linux系统或使用 su 命令切换到另一个用户时,设置用户环境第一个读取的文件就是 /etc/profile ,此文件为系统全局变量配置文件,且仅仅在第一次登录系统时才会全局运行 /etc/profile

注意上面描述的几个关键:

  • 设置用户环境第一个读取的脚本文件 可以推理出在它之后读取的文件设置环境变量将会会覆盖 /etc/profile 文件中配置的环境变量;
  • 仅仅在第一次登录系统时才会全局运行 /etc/profile 可以解释一个场景:我们在使用Ubuntu等桌面Linux系统时,用快捷键 ctrl+alt+t 打开的shell终端里,修改环境变量后使用source /etc/profile这个命令执行生效,新的环境变量只能在当前的终端里面有效,打开新的shell终端时,刚才有效的环境变量在新的终端是不生效的;所以全局生效 /etc/profile 环境变量的正确方式是注销重登录或者直接重启系统

以添加JDK的环境变量为例子,vim /etc/profile 打开文件, 在文件最后添加:

export JAVA_HOME=/opt/jdk1.8.0_191
export PATH=$JAVA_HOME/bin:$PATH

/etc/profile.d/ 目录

/etc/profile.d 目录中存放的是一些应用程序所需的启动脚本,比如vim等命令的一些附加设置,在 /etc/profile.d 目录下添加相关的环境变量设置的 .sh 脚本文件,这些脚本文件的环境变量能够被生效,是因为在 /etc/profile 被读取的时候,会使用一个for循环语句来调用 /etc/profile.d 下的脚本,这些脚本文件所设置的环境变量就和 /etc/profile 启动时一起被设置起来了,cat /etc/profile 可以看到有一段加载 /etc/profile.d 目录下所有 .sh 脚本文件的代码:

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

从上面的代码不难理解,/etc/profile.d/ 目录下设置环境变量和 /etc/profile 效果是一样的,都是全局环境变量,一旦生效后也都是永久环境变量; /etc/profile.d//etc/profile 好维护,不想要的环境变量从 /etc/profile.d/ 目录中移除即可,创建好的环境变量拷贝文件就轻松的移植到其他的计算机,不用每次去改动 /etc/profile 文件。

根据上面描述可以推理出:

  • /etc/profile.d 目录下的环境变量是 /etc/profile 启动时一起被读取,那么想要在当前shell终端临时生效可以使用 source /etc/profile,要全局生效则需要注销重登录或者直接重启系统,和 /etc/profile 原理一样;
  • /etc/profile.d 目录下的环境变量和 /etc/profile 的环境变量优先级,根据环境变量在 /etc/profile 的for循环语句调用 /etc/profile.d 的前面还是后面,在前则被 /etc/profile.d 目录下的环境变量覆盖,在后则被 /etc/profile 的环境变量覆盖

关于/etc/profile.d 目录,我使用我的Ubuntu 14.04.5系统,切换到 /etc/profile.d 目录,再使用 ls 命令列出目录下的所有脚本文件:

cd /etc/profile.d && ls

Ubuntu 14.04.5 在 /etc/profile.d 目录下默认带有这三个文件 appmenu-qt5.sh bash_completion.sh vte.sh

  • bash_completion.sh 是一个 bash-completion 软件包的脚本,这个脚本的作用是规定我们使用 Tab 键自动补全命令以什么样的参数去补全,有兴趣的可以自行深入了解;

还是以添加JDK的环境变量为例子,使用命令 sudo vim /etc/profile.d/java.sh 创建并编辑 java.sh 文件 (文件名可自行定义, .sh 类型即可),在文件中填如下面的内容:

# java env
export JAVA_HOME=/opt/jdk1.8.0_191
export PATH=$JAVA_HOME/bin:$PATH

/etc/environment 文件

/etc/profile 文件之后,登录系统时读取环境信息使用的第二个文件就是 /etc/environment 文件,理论上在这个文件中也可以设置环境变量,环境变量达到的效果也和 /etc/profile 文件的环境变量效果一样,全局永久的环境变量;

但是,最好别通过这个文件添加或修改环境变量,因为 /etc/profile 文件是面对系统用户的,填写错了大不了最多导致系统里的所有用户无法使用,但是 /etc/environment 文件是面对系统的,系统通过 /etc/environment 文件中的PATH去找对应的东西,以Ubuntu为例子,如果不小心更改 /etc/environment 文件中把PATH影响到,就无法进入桌面界面了,也无法使用一些命令了;

所以,/etc/environment 文件太重要了,仅仅想要设置一个全局的环境变量,完全没有必要用这个文件。

~/.bash_profile 文件

/etc/profile 文件之后,登录系统时读取环境信息使用的第三个文件是用户自己目录下的 .profile 文件,每个用户可使用属于自己的该文件输入只对自己生效的用户环境变量;

在不同的Linux操作系统下,这个文件名字可能是不同的,可能是~/.bash_profile~/.bash_login~/.bashrc~/.profile其中的一种或几种,在Ubuntu14.04.5下,我的用户文件夹下默认的有 .bashrc.profile 文件,他们的先后顺序cat ~/.profile 就可以知道,~/.bash_profile 会把 ~/.bashrc 先读取,如下:

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
    fi
fi

我在自己的Ubuntu14.04.5下做了一个测试,发现有个比较特殊的地方:

  • 如果将环境变量在 .profile 文件下配置, source ~/.profile 只在当前shell终端临时生效,永久生效环境变量依然需要注销重登录或者直接重启系统;
  • ~/.bashrc 文件中配置环境变量,保存之后打开新的shell终端就已经生效了,反而当前终端需要 source ~/.profile 才能生效,后面查询了一下原因:Ubuntu下 ~/.bashrc 是每次打开新的shell时,该文件被读取

设置临时环境变量

在shell终端直接运行 export 命令设置环境变量,该变量只在当前的shell终端或其子shell终端下是有效的,shell关闭了,变量也就失效了,再打开新shell终端时就没有这个变量,需要使用的话还需要重新设置; source /etc/profile 只能在当前shell终端有效其实就相当于执行export命令设置临时环境变量;

还是以添加JDK的环境变量为例子,在shell终端直接执行命令即可设置临时环境变量:

export JAVA_HOME=/opt/jdk1.8.0_191
export PATH=$JAVA_HOME/bin:$PATH

常用环境变量和命令注解

  1. 常用环境变量

我们在设置环境变量的时候,有很多已存在的通用环境变量,只需要通过$符号就可以直接拿过来使用

  • PATH: 预设可执行文件或命令的搜索路径;

可以利用 echo $PATH 查看当前当前系统PATH路径

  • USER: 用户登录时使用的用户名;
  • LOGNAME: 指当前用户的登录名;
  • HOSTNAME: 所使用的主机名,HOSTNAME在某些Linux系统中可能设置成HOST;
  • MAIL: 存放用户电子邮件的邮箱,没有设置的话就是空的;
  • HISTSIZE: 保存历史命令记录的条数;
  • HOME:用户的主工作目录;
  • SHELL:当前用户用的是哪种Shell;
  1. 查看环境变量相关的命令:
  • echo 显示某个环境变量值 比如:可以利用 echo $PATH 查看当前当前系统PATH路径;
  • env 显示所有环境变量
  • set 显示本地定义的shell变量
  • unset 清除环境变量