一、什么是环境变量
环境变量是bash shell的特性,用于存储shell会话和工作环境的信息。这项特性可以让用户在内存中存储数据,以便程序或shell中运行的脚本能够轻松访问到它们,这也是存储持久化数据的一种简便方法。
二、环境变量的分类
在bash shell中环境变量分为全局变量和局部变量。
全局变量对shell会话和所有的子shell都是可见的,可以使用env [param] 或 printenv [param] 查看全局变量。
局部变量只能在定义它们的进程中可见,目前没有比较好的办法单独查看局部变量,set命令会显示所有的变量包括全局、局部及用户自定义的变量。
三、操作环境变量
- 注意事项:
- 全局变量使用大写字母表示,用户自定义局部变量使用小写字母表示,变量名区分大小写
- 变量名、等号和值之间没有空格,如果在赋值表达式中加入了空格,bash shell就会把值当做一个单独的命令
- 设置用户自定义变量
- 设置局部变量,示例:
- 赋值:my_variable=hello 或 my_variable="Hello World"
- 获取并输出:echo $my_variable
- 设置全局变量
- 赋值:user_name=sawyer
- 导出:export user_name
- 获取并输出:echo $user_name
- 设置局部变量,示例:
- 删除环境变量:unset user_age
四、启动文件
当登录系统的时候启动一个bash shell时,默认情况下bash会在几个文件中查找命令,这些文件叫做启动文件或环境文件。bash检查的启动文件取决于启动bash shell的方式。
启动bash shell的方式有三种:
-
- 登录时作为默认登录shell
- 作为非登录shell的交互式shell
- 作为运行脚本的非交互式shell
接下来会介绍bash shell在不同的方式下的启动文件
-
登录shell
当登录Linux系统时,bash shell 会作为登录shell启动。登录shell会从5个不同的启动文件里读取命令:
- /etc/profile
- $HOME/.bash_profile
- $HOME/.bashrc
- $HOME/.bash_login
- $HOME/.profile
-
交互式shell
如果bash shell不是在系统登录时启动的,比如是在命令行提示符下敲入bash时启动,那么启动的shell叫作交互式shell。交互式shell不会访问/etc/profile文件,只会检查用户HOME目录中的.bashrc文件。通常.bashrc文件有两个作用:一是查看/etc目录下通用的bashrc文件,二是为用户提供一个定制自己的命令别名和私有脚本函数的地方。
-
非交互式shell
系统执行脚本时用的就是非交互式shell。当shell启动一个非交互式的shell进程时,它会检查环境变量BASH_ENV,查看要执行的启动文件。通常,这个变量在默认的情况下并未设置。如果当在系统上运行脚本时,希望能够预先运行一些特殊的命令或执行一些指定的操作,那么可以自定义设置BASH_ENV,如:BASH_ENV="/opt/bashenv.sh" && export BASH_ENV
五、环境变量持久化
当需要定义一些所有用户都需要使用的全局变量时,可能大部分人都会将新的或修改过的变量放在/etc/profile中,但这种方式并不是最佳的实践,因为/etc/profile会随着系统的升级而发生改变。/etc/profile的代码如下:
# /etc/profile # System wide environment and startup programs, for login setup # Functions and aliases go in /etc/bashrc # It's NOT a good idea to change this file unless you know what you # are doing. It's much better to create a custom.sh shell script in # /etc/profile.d/ to make custom changes to your environment, as this # will prevent the need for merging in future updates. pathmunge () { case ":${PATH}:" in *:"$1":*) ;; *) if [ "$2" = "after" ] ; then PATH=$PATH:$1 else PATH=$1:$PATH fi esac } if [ -x /usr/bin/id ]; then if [ -z "$EUID" ]; then # ksh workaround EUID=`/usr/bin/id -u` UID=`/usr/bin/id -ru` fi USER="`/usr/bin/id -un`" LOGNAME=$USER MAIL="/var/spool/mail/$USER" fi # Path manipulation if [ "$EUID" = "0" ]; then pathmunge /usr/sbin pathmunge /usr/local/sbin else pathmunge /usr/local/sbin after pathmunge /usr/sbin after fi HOSTNAME=`/usr/bin/hostname 2>/dev/null` HISTSIZE=1000 if [ "$HISTCONTROL" = "ignorespace" ] ; then export HISTCONTROL=ignoreboth else export HISTCONTROL=ignoredups fi export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL # By default, we want umask to get set. This sets it for login shell # Current threshold for system reserved uid/gids is 200 # You could check uidgid reservation validity in # /usr/share/doc/setup-*/uidgid file if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then umask 002 else umask 022 fi for i in /etc/profile.d/*.sh ; do if [ -r "$i" ]; then if [ "${-#*i}" != "$-" ]; then . "$i" else . "$i" >/dev/null fi fi done unset i unset -f pathmunge
这个/etc/profile文件是从CentOS7中得来的,从文件最后一段命令中可以看到,系统会遍历/etc/profile.d目录,并执行里面的.sh后缀的文件。所以,实际上我们在/etc/profile.d目录中,创建一个.sh结尾的文件,然后把全局变量写在这个文件中。
此外,值得注意的是,在大多数发行版中,存储个人用户永久性bash shell变量的地方是$HOME/.bashrc文件。这一点适用于所有类型的shell进程,但如果设置了BASH_ENV变量,那么除非它指向的是$HOME/.bashrc,否则你应该将非交互式shell的用户变量放置在别的地方。