2.2.4 环境变量
环境变量是指bash运行环境中的公共变量,这些变量的值在bash启动或运行时被设置,在该bash启动的程序可以读取这些变量的值,用作程序运行时的配置。环境变量非常有用,例如用户输入命令时用到的搜索路径、ls文件时显示颜色、Hadoop、HBase和Spark等各类系统的部署都要用到环境变量。本节将详细介绍环境变量的常用操作和设置方法。
1.查看环境变量
使用printenv打印bash的环境变量,命令如下。
该命令的部分输出结果如下所示,每一行就是一个环境变量的设置,其中,“=”的左侧是环境变量名,全部使用大写字母,如PWD、HOME、PATH全都是大写,如果一个环境变量名有很长,如SELINUX_ROLE_REQUESTED,则可以使用下画线(_)进行分隔;“=”的右侧是环境变量的值,例如PWD的值是/home/user,HOME的值是/home/user。在该bash上启动的程序,可以访问这些环境变量的值,并根据它们的值做不同的动作。
使用echo直接输出指定的环境变量的值,示例如下,输出PATH环境变量的值,其中$PATH表示PATH变量。
2.设置环境变量
(1)使用export设置环境变量
使用export命令设置环境变量的值,例如设置一个新的环境变量MY_ENV,将它的值设置成hello,命令如下。
可以用echo来打印变量MY_ENV的值,注意MY_ENV前面要加$。
如果要在已有的环境变量上增加内容,例如在MY_ENV变量后面增加新的字符串world,中间使用冒号(:)作为分隔,则可以使用$MY_ENV来表示该变量之前的值,示例如下。
打印环境变量MY_ENV的值,命令如下。
直接运行MY_ENV="hello",也可以对MY_ENV赋值,那么使用export和不使用export,有什么区别呢?
使用export设置的环境变量在bash的所有后代进程(不光是子进程,还有子进程的子进程等,世世代代下去)都可以访问到,而不使用export设置的环境变量则只能在bash的子进程中访问到,再下一代的进程就访问不到了。
可以做个简单的测试,先在bash A上使用export来设置MY_ENV,再运行bash命令,启动一个bash子进程B,在bash B上打印printenv,此时printenv是bash A的孙子进程了,仍然会输出MY_ENV的值,说明可以访问MY_ENV。同样的操作,如果不使用export来设置,直接用等于(=)来设置,则printenv打印出来的变量就没有MY_ENV了。
后续在bash A上使用Shell脚本编程,Shell脚本运行时,就会启动一个bash子进程B,Shell脚本中的命令C就是bash A的孙进程。如果希望Shell脚本中的命令能够访问bash A的环境变量,那么在bash A中设置这些环境变量时,就一定要使用export。
(2)使用unset去除环境变量的设置
使用unset命令,去除某个环境变量的设置,示例如下。
打印环境变量MY_ENV的值,可以看到不再有值输出。
3.自动设置环境变量
如果将环境变量的设置命令写入Linux运行时的初始化文件,可以实现环境变量的自动设置。常用的两个初始化文件是/etc/profie和~/.bashrc,说明如下。
(1)/etc/profie
/etc/profile用于全局设置,在该文件中设置的环境变量,不管这个bash的用户是谁,都会在每个bash中生效。环境变量设置通常添加在/etc/profile末尾,如下第87行所示。
(2)~/.bashrc
~/.bashrc用于和特定用户相关的配置,该配置只会对特定的用户生效,对于其他身份的用户无效。例如配置user用户~/.bashrc,该文件的路径为/home/user/.bashrc,示例如第12行所示。以user用户登录bash,或者以su - user切换到user的bash,或者以user身份直接运行bash时(非交互式登录),bash都会读取 .bashrc来设置环境变量。但是,如果以root用户登录或者切换到root用户时,这个环境变量就不会生效。
在初始化顺序上,/etc/profile在前,~/.bashrc在后;在作用范围上,/etc/profile对所有用户都生效,~/.bashrc只对当前用户有效;此外~/.bash_profile也有初始化功能,但是对于非交互式登录无效。
4.PATH环境变量
PATH环境变量非常重要,它用于bash中搜索路径的设置。PATH的值如下所示,有很多路径,每个路径之间使用冒号(:)进行分隔。
在bash上输入命令(如date),为何不需要输入date的绝对路径,bash就能够直接运行date命令呢?
这是因为有了PATH的设置,bash会首先到PATH所设置的路径中,去查找是否有date这个可执行文件,如果有,则立即执行,如果没有,就会提示Command not found。