Linux命令行-环境变量
在上一篇关于shell,子shell,进程相关介绍结束之后,接下来将要学习Linux中的环境变量。
环境变量
bash shell 会用一个叫作环境变量的特性来存储shell会话和工作环境的信息,这项特性允许我在内存中存储数据,这也是存储持久数据的方法。
一般来说,环境变量分为两类:全局变量和局部变量
虽然bash中会有使用一致的专用环境变量,但是不同的版本Linux经常会添加自有的环境变量。
全局环境变量
全局环境变量顾名思义就是对于shell和子shell都是可见的,而局部变量则只是对创建它们的shell可见。系统环境变量基本上都是大写的。
查看全局变量命令:env 或者 printenv
如下图:
这里只是其中一部分的全局环境变量,其中有很多都是在登录过程中设置的,另外,我们的登录方式也会影响到所设置的环境变量。
若是需要显示个别环境变量的值,使用printenv命令,但是不要使用env命令。
实例:
当然我们也可以使用echo来显示变量的值,不过在这种情况下使用某个环境变量时,必须要在变量前加上 $ 。
实例:
Tip:在echo命令中,在变量名前加上$ 可不仅仅是要显示变量当前的值,它能够让变量作为命令行参数。
那么是否可以用所有的子shell,当然是可以的。
实例:
上面我们可以看出,在子shell中显示的HOME环境变量的值和父shell中是一摸一样的。
局部环境变量
局部环境变量是只能在定义它们的进程中可见,虽然它是局部的但是和全局环境变量同等重要。事实上,Linux系统也默认定义了标准的局部环境变量,不过我们自己也可以定义自己的局部变量,这些被称为用户定义局部变量。
但是在Linux中并没有一个只显示局部环境变量的命令。set命令会显示特定进程设置的所有的环境变量,包括局部、全局和用户定义变量。
实例:
这只是set命令显示出来的部分环境变量,包含了全局环境变量。
Tip:命令env、printenv和set之间的差异很细微,set不仅仅会显示全部的环境变量还会按照字母的顺序进行排序,而env和printenv并没有这个功能,但是env相较于printenv来说还多出一个功能。
设置用户定义变量
上面介绍了两种不同类型的环境变量,那么对于用户自定义变量应该如何去创建并引用就是接下来需要学习的东西。
设置局部用户定义变量
在启动了bash shell之后,就可以创建在这个shell内可见的局部变量了,可以通过等号给环境变量赋值,值可以是数值或者是字符串。
实例:
非常的简单,当我们需要引用环境变量的值时,只要通过$my_variable引用即可。若是我们需要给变量赋一个含有空格的字符串值,必须使用单引号(双引号)来界定字符串的首尾。
实例:
Tip:所有的环境变量名都是使用大写字母,若是我们自己创建的局部变量一般使用小写字母以作区分,另变量名、等号和值之间没有空格,若是加上空格,bash可能会把值作为一个命令。
当我们设置了局部变量后,就可以在shell的任何地方使用它,但是若是我们在另外一个shell中使用它,结果就是不可用。同理,若是我们在子shell中设置了一个局部变量,一旦退出了子进程,这个局部变量就不可用了。为了解决这个问题,可以将局部的用户定义变量变成全局变量来改变这种情况。
设置全局环境变量
设置全局环境变量的进程及其子进程中,这个变量都是可见的,创建全局环境变量的方法是先创建一个局部环境变量,然后再把它导入到全局环境中。
需要命令:export
实例:
这个过程通过export命令来完成,变量名前不需要加$ 。bash命令启动一个子shell后,在这个子shell中仍能正确显示变量的值,该变量能保留住它的值是因为export命令使其成为了全局环境变量。
Tip:修改子shell中的全局环境变量不会影响父shell中该变量的值,子shell甚至无法使用export命令改变父shell中全局环境变量的值。
删除环境变量
上面我们学习了如何创建用户自定义变量,既然可以创建,那么也就可以删除。
命令:unset
Tip:不要使用$。
我们在涉及到环境变量名时,对于什么时候使用$,只需要记住一点:如果需要用到变量,就需要$,如果是操作变量,不使用$,规则有个例外就是printenv 来显示变量的值。
在处理全局环境变量时,和上述一个规则,若是在子shell中删除了一个全局环境变量,只对子shell有效,该变量在父shell中仍然可以使用。
实例:
默认的shell环境变量
在默认情况下,bash shell 都会使用一些特定的环境变量来定义系统环境,这些变量在Linux系统上就已经设置好了。
下表是一些bash shell 支持的变量:
除了上述默认的环境变量,bash shell 还提供了一些自有的变量:
这里就展示一部分,不是所有的默认环境变量都会在运行set命令时列出,尽管这些都是默认环境变量,但并不是每一个都必须有一个值。
设置PATH环境变量
当我们在shell命令行输入一个外部命令时,shell必须搜索系统来找到对应的程序,PATH环境变量定义了用于进行命令和程序查找的目录。
在当前系统环境下的目录如下:
PATH中的目录使用冒号进行分隔,输出显示了可供用来查找命令和程序。
如果命令和程序的位置不在PATH环境中,且不使用绝对路径的话,shell是没有办法找到的,这样就会产生一个问题,应用程序可执行文件一般不放在PATH的目录中,就需要我们将应用程序所在的目录放到PATH环境变量的目录中。其实这个步骤还是比较简单的,只需要把新的搜索目录添加到现在的PATH环境变量中,无需从头定义。
实例:
如上就已经成功将新的目录添加到了PATH环境变量中了,当我们加入PATH环境变量之后,我们就可以在虚拟目录的任何位置执行程序了。
Tip:如果我们希望shell能够找到我们程序的位置,要记得把修改的PATH环境变量导出(export命令)。
一般来说,程序员会将单点符也加入PATH环境变量,单点符表示当前目录。不过对于PATH环境 变量的修改只能持续到退出或者重启系统,并不能一直持续,下面会来学习如何永久保持环境变量的修改效果。
定位系统环境变量
环境变量在linux系统中的用途有很多,上面我们学习了如何修改系统的环境变量,也知道如何创建自己的环境变量,那么我们就要学习如何使得它的作用更加持久化。
在我们登入Linux系统并且启动一个bash shell时,默认情况下bash会在几个文件中查找命令,这些文件叫做启动文件,bash检查的启动文件主要取决于启动bash shell的方式:
1.登录时作为默认的登录shell
2.作为非登录shell的交互式shell
3.作为运行脚本的非交互shell
登录shell
当我们登录Linux系统时,bash shell 作为登录shell 启动,会从五个不同的启动文件中读取命令:
第一个文件 /etc/profile 是系统上默认的bash shell 的主启动文件,每个用户登录都会执行。
Tip:需要注意的是有些Linux开发版使用的是PAM(可拆卸式认证模块),这种情况下,PAM文件会在bash shell 之前启动处理,这些文件会包含环境变量。
另外的四个启动文件是针对用户的个人需求定制的,来仔细看看各个文件。
/etc/profile 文件:
这个文件上面介绍过了,上图是它在ubuntu系统中的样子。这里面的大部分细节和语法会在之后的章节具体学习。
在诸多Linux开发版的系统中,启动主文件都用到了一个共同的特性:for语句,主要是用来迭代 /etc/profile.d 目录下的所有文件。(这是一个为Linux系统提供了一个放置特定程序启动文件的地方),在ubuntu系统下该文件主要包含了以下这些:
Tip:两个文件的主要区别在于,/etc/profile 是储存命令的,而 /etc/profile.d 主要是存放命令中所需的可执行文件的。
在上述可执行文件中大部分都是使用 .sh扩展名(供bash shell使用),还有另外一种使用 .csh扩展名(供C shell使用)。
$HOME 目录下的启动文件:
剩下这些启动文件都是起到一个作用:提供一个用户专属的启动文件定义所用到的环境变量。一般来说,大多数都只会使用到一到两个。
需要知道的是,剩下这四个文件都是以点号开头,这就说明这些是隐藏文件(不会在通常的 ls 指令的输出列表中出现),它们位于用户的HOME目录下,所以每个用户都可以编辑这些文件并且添加自己的环境变量,这些环境变量会在每次启动shell会话时生效。
Tip:$HOME表示某个用户的主目录,它和波浪号(~)的作用是一样的。
交互式shell进程
若是我们的bash shell 不是登录系统时启动的,那么启动的就是交互式shell,不会像登录shell 一样运行,依然会提供命令行提示符来输入命令,若是bash作为交互式shell启动,那么它就不会访问 /etc/profile 文件了,只会检查用户HOME目录中的. bashrc 文件。
实例:
这是在ubuntu系统中,. bashrc 文件的部分命令。
. bashrc 文件有两个作用:一个是查看/etc目录下通用的bashrc文件,二是为用户提供一个定制自己的命令别名和私有脚本函数的地方。
非交互式shell
最后一种就是非交互式的shell,系统执行shell脚本时用的就是这种shell,不同的地方在于它没有命令行提示符。脚本能以很多不同的方式运行,但是只有某一些方式能够启动子shell 。
为了能够处理这样的情况,bash shell 提供了BASH_ENV 环境变量。当shell 启动一个非交互式的进程时,它会检查这个环境变量来查看要执行的启动文件,若是有指定的文件,shell会执行该文件中的命令,也包括一些变量的设置。
BASH_ENV 环境变量在默认情况下并没有被设置,在这情况下 printenv 命令只会返回CLI提示符:
输入echo 命令会显示一个空行,然后返回CLI命令提示符:
如果BASH_ENV变量没有设置,shell脚本一般会从父shell 中继承导出过的变量,若是脚本不启动子shell的话,变量已经存在于当前的shell中了,就算没有设置,也可以使用当前shell 的局部和全局变量。
环境变量的持久化
上面学习了全局环境变量和局部环境变量,以及shell的四种类型:登录、非登录、交互和非交互,接下来就正式进入主题:找出永久性的环境变量和自己创建永久性的全局变量或者是局部变量。
对于全局变量来说,我们一般将修改过的或者是新的变量放在 /etc/profile.d 目录下的一个以 .sh 结尾的文件里较为合适。相较之下,/etc/profile 这个文件会随着系统升级而产生变化,当然还有一个更好的选择,就是$HOME/.bashrc文件,该点适用于所有类型的shell进程,若是设置了BASH_ENV变量,那么若是该变量不指向 $HOME/.bashrc 文件,应当将非交互式shell的用户变量放在别的地方。(原因:非交互式shell不会读取 .bashrc文件。)
当我们知道了这个,在命令行这片博客中说过 alias 命令设置就是不能够持久存在下去,现在可以将alias 放置在 .bashrc 文件中,使得其效果永久化。
数组变量
环境变量还有一点非常好,那就是可以作为数组来使用,和C语言中的数组本质相同,但是在具体使用细节略微有不同。
实例:
首先自己创建一个数组,和之前学习一样,可以使用通配符进行简略的书写,也可以使用标号进行单独位置的显示,也可以对单独位置的信息进行更改。最后一个命令就是删除整个数组,也可以进行单独的删除。但是数组变量会使得程序变得很麻烦,所以总体上一般不会太频繁的使用到这个变量。
小结
到此关于环境变量的介绍就结束了,全局环境变量可以在父进程和子进程中使用,局部环境变量只能在定义它们的进程中使用,还学习了Linux使用全局环境变量和局部环境变量存储环境信息,可以通过shell命令行界面和shell脚本来访问,还学习了登录和非登录,交互和非交互shell之间的区别。
接下来将要学习的是Linux的文件权限,这相对来说还是比较难的。