从零开始学Linux(七)
上一篇文章把Shell的来龙去脉捋清楚了从Shell的类型、父子关系到内建命令和外部命令的区别总算是把终端背后的运行机制弄明白了。今天继续往下走课程推进到了环境变量这一章。说实话环境变量这个词我其实早就见过之前在配置Java开发环境的时候照着网上的教程设置过JAVA_HOME但当时完全是照抄命令根本不知道自己在干什么也不知道为什么要往.bashrc里写那几行。这次借着课程的机会把环境变量从头到尾好好理解了一遍。先说最基础的概念。环境变量是存储在程序外部的一种变量通常通过操作系统或微服务内置的功能设置由名称和值组成格式是VARIABLE_NAMEvalue这样的形式可以在任何时间点进行引用。bash shell用环境变量的特性来存储有关shell会话和工作环境的信息这也是它们被称作环境变量的原因。这项特性允许在内存中存储数据以便程序或shell中运行的脚本能够快速访问到它们这是一种存储持久数据的简便方法。bash shell的环境变量分为两类。全局环境变量对于shell会话和所有生成的子shell都是可见的查看全局变量可以使用env或printenv命令。要显示个别全局环境变量的值可以直接使用printenv命令加上变量名或者用env命令配合grep来检索。也可以使用echo显示变量的值但引用环境变量的时候必须在变量前面加上一个美元符。我之前一直不太明白为什么echo HOME就能显示出家目录的路径现在清楚了美元符的作用就是告诉shell去读取这个变量的值而不是把它当成普通文本。为了验证全局变量可以被子shell继承我输入bash命令进入子shell然后执行echoHOME就能显示出家目录的路径现在清楚了美元符的作用就是告诉shell去读取这个变量的值而不是把它当成普通文本。为了验证全局变量可以被子shell继承我输入bash命令进入子shell然后执行echoHOME显示的结果和父shell中一模一样。局部环境变量则只能在定义它们的进程中可见Linux系统并没有一个只显示局部环境变量的专门命令set命令会显示为某个特定进程设置的所有环境变量包括局部变量、全局变量以及用户自定义变量并且会按照字母顺序对结果进行排序。自己定义环境变量也是通过等号赋值来实现的值可以是数值或字符串。变量名区分大小写所有的系统环境变量名都用大写字母这是bash shell的标准惯例。如果是自己创建的局部变量或是shell脚本里的变量应该使用小写字母这样能避免重新定义系统环境变量可能带来的灾难。变量名、等号和值之间不能有空格如果要给变量赋一个含有空格的字符串值必须用单引号来界定字符串的首和尾。我在父shell中定义了一个局部变量my_variableHello World然后用echo myvariable能正常显示但进入子shell后再执行echomyvariable能正常显示但进入子shell后再执行echomy_variable就什么都没有了证明局部变量确实只在当前shell中可见。要让一个变量变成全局环境变量需要先用等号创建一个局部环境变量再通过export命令把它导出到全局环境中。我把刚才那个my_variable用export导出之后再进入子shell就能正常看到它的值了。但我又试了一下在子shell中重新定义这个变量并再次export退出子shell回到父shell后查看发现父shell中的值并没有改变这说明子shell对环境变量的修改不会影响到父shell每个shell都有自己的环境变量副本。删除环境变量用的是unset命令用法是unset加变量名。这里有个细节要注意引用环境变量的时候用美元符但操作变量的时候不要用美元符。我试了unset my_variable之后再用echo查看果然什么都没了。但这样删除的环境变量只是当前会话中生效重新启动shell之后就又没了因为我在.bashrc里并没有写入这个变量的定义所以每次新启动的shell都不会加载它。说到持久化这就是PATH环境变量出场的时候了。当在shell命令行中输入一个外部命令时shell必须搜索系统来找到对应的应用程序PATH环境变量定义了用于进行命令和程序查找的目录这些目录用冒号分隔。我echo PATH看了一下里面有好几个目录包括/usr/bin、/bin等所以之前从apt下载的应用程序都在这些目录下才能直接输入程序名就调用。如果自己在一个目录下安装了应用程序想直接输入程序名就运行有两种办法一种是在命令行输入完整的路径加可执行文件名另一种就是把应用程序的目录添加到PATH环境变量中。添加的命令是exportPATHPATH看了一下里面有好几个目录包括/usr/bin、/bin等所以之前从apt下载的应用程序都在这些目录下才能直接输入程序名就调用。如果自己在一个目录下安装了应用程序想直接输入程序名就运行有两种办法一种是在命令行输入完整的路径加可执行文件名另一种就是把应用程序的目录添加到PATH环境变量中。添加的命令是exportPATHPATH:/自定义目录意思就是在原来的PATH值基础上追加一个新的目录。但这样修改只在当前shell会话中有效退出或重启后就没了。如果想让修改永久生效需要把这条export命令写入到~/.bashrc文件中因为每次启动系统都会自动执行.bashrc中的所有命令行。我跟着做了一遍vim ~/.bashrc打开文件在末尾加上export PATH$PATH:/home/zz/myapp保存退出后执行source ~/.bashrc让配置立即生效之后就能在任何目录直接调用我自己的程序了。环境变量在整个Linux系统中的存储是分层级的。登录Linux系统启动bash shell时bash会作为登录shell启动从多个启动文件里读取命令。系统级的/etc/profile是主启动文件系统上每个用户登录时都会执行它它还会遍历/etc/profile.d目录下的所有.sh脚本文件。用户级的启动文件位于HOME目录中包括.profile、.bashrc、.bash_login、.bash_profile这四个隐藏文件。实际登录时shell会依次查找这些文件并按顺序执行。每个用户都能在自己的HOME目录下创建专属的启动文件来定义自己所用的环境变量互不干扰。最后是数组变量这是环境变量的一个特殊形式Bash Shell只支持一维数组。数组用括号来表示元素用空格分隔语法是array_name(value_1 value_2 ... value_n)。引用数组中某个元素的值需要用它在数组中的位置索引值格式是arrayname[index]索引从0开始。要显示整个数组变量可以用星号作为通配符放在索引值的位置。我创建了一个数组变量students(AliceBobCharlieDavid)然后echoarrayname[index]索引从0开始。要显示整个数组变量可以用星号作为通配符放在索引值的位置。我创建了一个数组变量students(AliceBobCharlieDavid)然后echo{students[0]}显示了Aliceecho ${students[*]}显示了全部成员。修改数组某个位置的元素用等号赋值就行students[1]Bruce。删除数组中的某个值或整个数组使用unset命令unset students[2]会删除索引2对应的元素但会保留这个索引位置为空unset students则直接删除了整个数组。把今天的内容和之前的串在一起看环境变量其实处处都在。之前用echo PATH查看路径、用echoPATH查看路径、用echoHOME回到主目录、在脚本里写#!/bin/bash指定解释器路径背后都是环境变量在工作。内建命令和外部命令的区别也和环境变量有关外部命令就是靠PATH环境变量里的路径被找到的。之前配置vim编辑器的时候在.bashrc里设置过别名今天又理解了怎么在.bashrc里定义环境变量和修改PATH这些启动文件的用途算是彻底搞清楚了。后续使用中肯定还会碰到更多与环境变量打交道的场景比如配置各种开发工具的时候至少现在知道该往哪里写了。希望这篇文章能给正在理解环境变量概念的同学一些参考有问题欢迎来交流