6.系统变量和环境变量

6.1.shell环境变量

在Linux中,很多程序和脚本都通过环境变量来获取系统信息,存储临时数据,配置信息。环境变量是指用来存储有关shell会话和工作环境信息,允许你在内存中存储数据,以便程序或shell中运行的脚本能够轻松访问到它们。也是存储持久数据的一种简便方法。在bash shell中,环境变量分为:全局和局部二类环境变量。

6.1.1.全局环境变量

全局环境变量对于shell会话和所有生成的子shell都是可见的。局部变量则只是创建它们的shell可见。在linux系统中有系统环境变量,它们基本都是使用全大写字母,以区别普通用户的环境变量。要查看系统全局变量,可以使用env命令, 如下图所示:
6. ubuntu的实践——系统变量和环境变量

要查看个别的环境变量的值,可以使用printenv命令, 如下图所示:
6. ubuntu的实践——系统变量和环境变量

正如前面所说的,全局变量在所有生成的子shell都是可见的,下面是用子shell输出USER全局变量,如下所示:
6. ubuntu的实践——系统变量和环境变量

6.1.2. 局部环境变量

局部环境变量虽然是局部的,但和全局环境变量一样重要。在linux操作系统上有默认全局环境变量也有局部环境变量,用户也可以自定义局部变量。使用set 命令会显示某个指定进程下的所有环境变量,包括全局,局变,用户自定义变量。

6.2.用户自定义变量

6.2.1.自定义局部变量

下是自定义一个局部变量,使用echo来声明一个变量名my_variable,并赋值一个字符串(也可是数字)。然后再使用echo输出该变量的值。如下图所示:
6. ubuntu的实践——系统变量和环境变量

要注意的点是:声明变量名时必须加$关键词, 赋值时不要加$关键词,输出时要加$关键词,也可以说使用echo时都要加$。变量名,等号,值三者之间不能有空格。如果变量值有空格时,必须加双引号。如下所示:

6. ubuntu的实践——系统变量和环境变量

如果是在子shell中,那该变量就不存在,退回主线程还是存在,如下图所示:
6. ubuntu的实践——系统变量和环境变量

6.2.2.自定义全局变量

设定了全局变量,在该进程所创建的子进程中,该变量都是可见的。创建全局变量的方法是先创建一个局部变量,然后导出到全局环境中。通过export来导出,变量名前面不加$。如下图所示:

6. ubuntu的实践——系统变量和环境变量

在子shell中修改全局变量并不会影响到父shell中该变量的值。这种改变仅在子shell中有效。并不会反映到父shell中。如下图所示:

6. ubuntu的实践——系统变量和环境变量

6.2.3.删除环境变量

要删除环境变量可以用unset命令,在unset引用变量名时,不要加$。
6. ubuntu的实践——系统变量和环境变量

6.3.shell环境变量中的系统全局环境变量

默认情况下, bash shell会用一些特定的环境变量来定义系统的环境。这些默认环境变量可以理解是上篇所讲的系统全局环境变量。

6.3.1.bash shell支持的Bourne变量

Bourne shell 是 UNIX 最初使用的 shell。下面例举几个常用的变量名。

变量名 描述
HOME 当前用户的主目录
PATH Shell查找命令的目录列表,由冒号分隔
PS1 Shell命令行界面的主提示符
PS2 Shell命令行界面的次提示符

如下图所示:使用echo 输出该变量名$PATH的值。值给出了shell查找命令会去的6个目录。优先最高的是/usr/local/bin 目录下。
6. ubuntu的实践——系统变量和环境变量

下面是主提示符与次提示符:
6. ubuntu的实践——系统变量和环境变量

6.3.2.bash shell 环境变量

下面只是随意列出了几个变量名。像BASH_SUBSHELL在介绍子shell中有讲过。

变量名 描述
BASH_SUBSHELL 当前子shell环境的嵌套级别。
BASH_VERSION 当前运行的bash shell 版本号。
HOSTNAME 当前主机名称
PWD 当前工作目录,对应内部命令小写pwd

下面随变演示一个,查看bash shell版本号:

6. ubuntu的实践——系统变量和环境变量

6.4.PATH环境变量

上面讲到了PATH变量,它的作用是:当你在shell命令行中输入一个外部命令时。Shell必须搜索系统来找到对应的程序。 PATH环境变量定义了用于进行命令和程序查找的目录。上面列出了要查找的6个目录。如果命令或者程序的位置没有包括在PATH变量中,那就必须使用绝对路径来查找,否则shell是无法找到的。找不到,它会产生一个错误信息。
如下图所示:mysqld服务之所以能找到,是因为它存在于/usr/sbin目录下。Mysql的mssqldump工具包之所以能找到,是因为它存在于/usr/bin目录下。这二个目录都是存在于PATH全局变量中。而nginx服务命令却未找到。
6. ubuntu的实践——系统变量和环境变量

在重新加载nginx配置文件时,会提示未找到命令
      
6. ubuntu的实践——系统变量和环境变量

下图来查找下nginx 服务是存放于哪个目录下。通过下图知道,nginx服务存在于/usr/local/nginx/sbin 目录下。而PATH环境变量中没有该路径。所示“提示未找到命令…“。
6. ubuntu的实践——系统变量和环境变量

如果想在虚拟目录任意位置操作nginx服务,又不想每次都用cd绝对路径定位。有二种方法:1是前面章节所学的软链接,把nginx的绝对路径能过软链接指定到PATH环境下的一个目录下。2是将nginx绝对路径添加到PATH目录中。

6.4.1.添加PATH环境变量

上面讲到了nginx服务, 下面演示将nginx服务的绝对路径,添加到PATH环境变量中。如下图所示:已将nginxx服务路径添加到了PATH环境变量中。
6. ubuntu的实践——系统变量和环境变量

下面来试试,在任意的虚拟目录下,执行nginx服务。下面是随意在虚拟目录的根目录下查看nginx服务, 重新加载nginx服务,该命令也找到了,下图的错误是nginx进程没有启动,与要介绍的PATH没有关系。
6. ubuntu的实践——系统变量和环境变量

总结: 当初学linux的时候,每当安装了一个服务时,在终端敲bash执行该命令,经常提示未找到该命令。但有些服务又可以直接找到。现在明白了, shell查找命令会去指定的PATH环境目录下查找。当有些服务安装后,该服务的bin目录并没有在PATH环境目录中。

6.5.系统环境变量位置

在上章中,知道了如何修改系统环境变量,如PATH变量,以及创建自己的全局环境变量和局部环境变量。这篇学习怎么让环境变量的作用持久化。在此之前,先了解下系统环境变量文件会在哪些位置,当使用bash shell时,bash是如何查找环境变量位置的。下面先来介绍几个文件,这些文件叫启动文件或叫环境文件。
bash检查的启动文件(环境文件)取决于你启动bash shell的方式。启动bash shell有3种方式:
(1)登录时的默认登录shell。
(2)交互式shell。
(3)运行脚本的非交互式shell。

6.5.1.登录shell

登陆shell是指:
(1) 用户登陆时,输入用户名和密码后启动的shell(例如使用ssh登录远程主机等);
(2) 通过带–login参数的命令:bash --login而启动的shell。当登录linux系统时,bash shell作为登录shell启动,登录shell会从5个不同的启动文件里读取命令。包括:

  • /etc/profile,
  • $HOME/.bash_profile,
  • $HOME/.bashrc,
  • $HOME/.bash_login,
  • $HOME/.profile

/etc/profile文件是系统默认的bash shell的主启动文件。另外4个启动文件是针对用户的(不同发行版中,四个启动文件一般都只有一到二个),可根据个人需求定制。

6.5.1.1. /etc/profile文件

只要登录了linux系统,bash就会执行/etc/profile启动文件中的命令(不同发行版的/etc/profile,有不同的设置和命令),profile文件内容如下图所示:
6. ubuntu的实践——系统变量和环境变量

profile文件内容太长,截取了一段。 上图有个for语句,它用来循环读取/etc/profile.d目录下的所有文件。该文件目录包含以下文件,如下图所示:
6. ubuntu的实践——系统变量和环境变量

上图启动文件中sh后缀的供bash shell 使用, csh后缀的供 c shell使用。lang.csh和lang.sh文件会尝试去判定系统上采用的默认语言字符集。对应LANG环境变量。

6.5.1.2.$HOME目录下的启动文件

HOME目录下的隐藏文件,找到了$HOME/.bash_profile, $HOME/.bashrc。每个用户都可以编辑这些文件添加自己的环境变量,这此环境变量会在每次启动 bash sehll 会话时生效。 HOME目录如下图所示:
6. ubuntu的实践——系统变量和环境变量

.bash_profile启动文件会先去检查HOME目录下是不是有一个叫.bashrc的启动文件,如果有就会先执行里面的命令。bash_profile文件内容如下图所示:
6. ubuntu的实践——系统变量和环境变量

上图中,可以看到在.bash_profile文件中给PATH变量添加了一个目录路径,并用export PATH 导入到全局中。在.bash_profile文件中加的变量可以持久化。
Ubuntu没有bash_profile

6.5.2.交互式shell进程

交互式shell是指:就是在终端上执行,shell等待你的输入,并且立即执行你提交的命令。命令行提示符输入命令,只会检查用户HOME目录中的.bashrc文件。 该文件两个作用:

  1. 是查看/etc目录下通用的bashrc文件
  2. 是为用户提供一个定制自己的命令别名(前面讲alias命令)和私有脚本函数(后面介绍)。 .bashrc文件内容如下图所示:

6. ubuntu的实践——系统变量和环境变量

6.5.3.非交互式shell

非交互式shell是指:以shell script(非交互)方式执行。在这种模式下,shell不与你进行交互,而是读取存放在文件中的命令,并且执行它们。当它读到文件的结尾EOF,shell也就终止了。 系统执行shell脚本时用的这是这种shell。区别是它没有命令提示符。但当你的系统上运行脚本时,也许希望能够运行一些特定启动的命令。
为了处理这种情况bash shell提供了BASH_ENV环境变量。当shell 启动一个非交互式shell进程时,它会检查这个环境变量来查看要执行的启动文件。默认情况下并未设置该变量,使用printenv命令只返回提示符:
6. ubuntu的实践——系统变量和环境变量

正如上图所示:BASH_ENV环境变量没有设置值。这种非交互式shell 一般通过启动一个子shell来执行。如果父shell是登录shell,那么可以从/etc/profile,/etc/profiled/*.sh和$HOME/.bashrc文件中继承这些变量。如果父shell中的变量是局部变量时,那么子shell无法继承。如果不启动子shell, 变量已存在于当前shell中,就算不设置BASH_ENV,也可以使用当前的局部和全局变量。

交互式与非交互式二者区别:读取的配置文件不同,交互式bash必然读取~/.bashrc文件;非交互式bash读取的是环境变量BASH_ENV(通常情况下)所指定的配置文件。

6.6.环境变量持久化

上面了解了各种shell进程对应的环境文件,找出永久性环境变量就容易多了。可以利用这些文件来创建自己的永久性全局变量或局部变量。全局变量是对所有用户都需要使用的变量,可以将新的变量或修改过的变量设置放在/etc/profile文件中,但升级了发行版该文件也会更新,所以这点要注意 (对所有用户)。

最好是在/etc/profile.d目录中创建一个以.sh结尾的文件,把所有新的变量或修改过的变量全部放在此文件中(对所有用户)。

对于存储个人用户永久性bash shell变量的地方是$HOME/.bashrc文件。这一点适用于所有类型的shell进程(仅对当前用户)。

下面来演示给mysql工具包路径,添加到PATH全局变量中:
(1)在虚拟根目录下输入mysqldump 工具,提示未找到命令,如下图所示:
6. ubuntu的实践——系统变量和环境变量

(2)找到mysqldump工具包的位置,路径是/usr/local/mysql/bin。如下图所示:
6. ubuntu的实践——系统变量和环境变量

(3)查看现有PATH的路径列表,以冒号分隔的默认有5个路径。如下图所示:
6. ubuntu的实践——系统变量和环境变量

(4)在$HOME/.bash_profile文件中加入一个PATH全局变量值,路径为/usr/local/mysql/bin。如下图所示:
6. ubuntu的实践——系统变量和环境变量

(5)exit退出终端或shutdown后重新开机,在虚拟根目录下输入mysqldump 工具,PATH设置的mysql工具包路径永久生效。如下图所示:
6. ubuntu的实践——系统变量和环境变量

再切换到mysql用户下,PATH的设置也是生效的,说明是跨用户生效的。
6. ubuntu的实践——系统变量和环境变量

在root用户下,使用子shell, PATH的设置也是生效的,说明跨进程,已设置成了全局变量。
6. ubuntu的实践——系统变量和环境变量

(6)最后在看下PATH路径,/usr/local/mysql/bin 已添加了
6. ubuntu的实践——系统变量和环境变量

相关文章: