一、什么是环境变量
环境变量是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
- 其中/etc/profile是bash shell默认的主启动文件,只要登录了系统,bash就会执行/etc/profile启动文件的命令;$HOME目录下的文件用于提供一个专属的启动文件来定义该用户所用到的环境变量。shell会按照$Home/.bash_profile、$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.d目录中,创建一个.sh结尾的文件,然后把全局变量写在这个文件中。
此外,值得注意的是,在大多数发行版中,存储个人用户永久性bash shell变量的地方是$HOME/.bashrc文件。这一点适用于所有类型的shell进程,但如果设置了BASH_ENV变量,那么除非它指向的是$HOME/.bashrc,否则你应该将非交互式shell的用户变量放置在别的地方。