使用Linux环境变量——第六章
2017-11-19 00:00
302 查看
摘要: 《Linux命令行与shell脚本编程大全》使用Linux环境变量——第六章
在bash shell中,环境变量分为两类:
全局变量
局部变量
本节将描述以上环境变量并演示怎么查看和使用它们。
全局环境变量对于shell会话和所有生成的子shell都是可见的。局部变量则只针对创建他们的shell可见。
Linux 系统在你开始bash会话时就设置了一些全局环境变量,系统环境变量基本上都是用大写字母,以区别于普通用户的环境变量。
登录方式也会影响到所设置的环境变量
要显示个别环境变量的值,可以使用printenv命令,但是不要使用env命令。
也可以使用echo显示环境变量额值。在这种情况下引用某个环境变量的时候必须在变量前面加上美元符($)。
在echo 命令中,在变量名钱加上$可不仅仅是要显示变量当前的值。它能够让变量作为命令行参数。
正如前面提到的,全局变量可作用于进程的所有子shell。
查看局部环境变量的列表有点复杂,没有一个只显示局部环境变量的命令。set 命令会显示某个特定进程设置的所有环境变量,包括局部变量,全局变量,以及用户定义变量。
env、printenv和set 之间差异很细微。set命令会显示出全局变量、局部变量及用户自定义变量,它还会按照字母顺序对结果进行排序。env、printenv 命令与set命令区别在于前两个命令不会对变量排序,也不会输出局部变量及用户自定义变量。
设置用户自定义变量非常简单,如果给变量赋值一个含有空格的字符串值,必须用引号界定字符串的首和尾。
如果没有引号的话,bash shell 会以为下一个词是一个要执行的命令。
敲门:所有环境变量名均使用大写字母,这是bash shell 的标准惯例,如果是你自己创建的局部变量或是shell脚本,请使用小写字母。变量名区分大小写。在涉及用户自定义的局部变量时坚持使用小写字母,这能够避免重新定义系统环境变量可能带来的灾难。
记住,变量名、等号和值之间没有空格,这一点非常重要,如果在赋值表达式中加上了空格 bash shell就会把值当成一个单独的命令。
设置了局部环境变量后,就能在shell进程的任何地方使用它了。但是如果生成了另外一个shell ,它在子shell中就不可用。
当你退出了子进程,那个局部环境变量就依然可用。
类似的,如果在子进程中设置了一个局部变量,那么一旦你退出了子进程,那个局部环境变量就不能用了。
当我们回到父shell时,子shell 中设置的局部变量就不存在了。可以通过将局部的用户定义变量编程全局变量来改变这种情况。
这个过程可以通过export 命令来完成,变量名前不需加 $ 。
定义并导入局部环境变量my_variable 后,bash命令启动了一个子shell,在这个子shell中能够显示出变量my_variable的值。该变量能够保留它的值是应为export命令使其变成了全局变量。
修改子shell中的全局变量并不会影响到父shell中该变量的值。
子shell 甚至无法使用export 命令改变父shell中全局变量的值。
尽管子shell重新定义并导出了变量my_variable,但父shell中的my_variable变量依然保留着原先的值。
窍门:在涉及环境变量名时,什么时候该使用$,什么时候不该使用$,如果用到变量,使用$ ; 如果要操作变量,不使用$ 。 这条规则有一个意外就是使用 printenv 显示某个变量的值时。
如果你再子进程中删除了一个全局环境变量,这只对子进程有效。该全局变量在父进程中依然可用。
和修改变量一样,在子shell中删除环境变量后,你无法将效果反映到父shell中。
出了默认的Bourne的环境变量,bash shell 还提供了一些自有的变量。
并不是所有的默认环境变量都会在运行set 命令时列出,尽管这些都是默认的环境变量,但并不是每一个都必须有一个值。
PATH 中的目录使用冒号分隔。
如果命令或者程序的位置没有包括在PATH 变量中,那么如果不使用绝对路径,shell是没法找到的。如果shell找不到指定命令或者程序,它会产生一个错误信息:
可以把新的搜索目录添加到现有的PATH环境变量中,无需从头定义。PATH中各个目录之间使用冒号分隔的,你只需要引用原来的PATH 值,然后再给这个字符串添加新的目录进行了。可以考虑一面的例子。
如果希望子shell 也能找到你的程序位置,一定要记得把修改后的PATH 环境变量导出
程序员通常办法是将单点符也加入PATH环境变量。该单点符代表当前目录
对PATH 变量的修改只能持续到退出或者重启系统。这种效果并不能一直持续。下节将介绍如果持久保持环境变量的修改效果。
登录时作为默认登录shell
作为非登录shell的交互式shell
作为运行脚本的非交互shell
/etc/profile
$HOME/.bash_profile
$HOME/.bashrc
$HOME/.bash_login
$HOME/.profile
/etc/profile 文件是系统上默认的bash shell的主启动文件。系统上的每个用户登录时都会执行这个启动文件。
另外4个启动文件是针对用户的,可根据个人需求定制
1./etc/profile文件
/etc/profile 文件是bash shell 默认的主启动文件,只要你登陆了Linux系统。bash就会执行/etc/profile 启动文件中的命令。
用到了一个特性 for 语句。它用来迭代/etc/profile.d 目录下的所有文件。(该语句在13节中详述) 这为Linux系统提供了一个放置特定应用程序启动文件的地方,当用户登录时,shell会执行这些文件, /etc/profile.d 目录下包含以下文件:
不难发现,有些文件与系统中的特定应用有关。大部分应用会创建两个启动文件:一个供bash shell使用(使用.sh扩展名),一个供c shell 使用(使用.csh扩展名)。
lang.csh 和 lang.sh 文件会尝试去判断系统上所采用的默认语言字符集,然后设置对应的LANG环境变量。
2.$HOME目录下的启动文件
剩下的启动文件都起着同一个作用:提供一个用户专属的启动文件来定义该用户所用到的环境变量。大多数Linux发行版只用这四个启动文件找那个的一到两个。
$HOME/.bash_profile
$HOME/.bashrc
$HOME/.bash_login
$HOME/.profile
注意,这四个文件都是以点号开头,这说明它们是隐藏文件(不会再通常的ls命令输出列表中出现)。它们位于用户的HOME目录下,所以每个用户都可以编辑这些文件并添加自己的环境变量,这些环境变量会在每次启动bash shell 会话时生效。
shell会按照以下顺序,运行第一个被找到的文件,余下的则被忽略:
$HOME/.bash_profile
$HOME/.bash_login
$HOME/.profile
这个列表并没有$HOME/.bashrc文件。这是因为该文件通常通过其他文件运行的。
CentOS Linux 系统中的.bash_profile 文件内容如下:
.bash_profile启动文件会先去检查HOME目录中是不是还有一个叫.bashrc的启动文件。如果有的话,会先去执行启动文件里面的命令。
如果bash是作为交互式shell启动的,它就不会访问/etc/profile文件,只会检查用户HOME目录中的.bashrc文件
CentOS系统上,这个文件看起来如下:
.bashrc文件有两个作用:一是查看/etc目录下通过的bashrc文件,而是为用户提供一个定制自己的命令别名(参看第五章)和 私有脚本函数 (将在第17章讲到) 的地方。
窍门:脚本能以不同的方式执行。只是其中的某一些方式能够启动子shell。你会在第11章中学习到shell不同的执行方式。
为了处理这种情况,bash shell 提供了BASH_ENV 环境变量。当shell启动一个非交互式shell进程时,它会检查这个环境变量来查看要执行的启动文件。如果有指定的文件,shell会执行该文件里的命令,这通常包括shell脚本变量设置。
在默认的CentOS中 这个环境变量在默认情况下并未设置。如果变量未设置,printenv 命令会返回CLI提示符:
那如果BASH_ENV 变量没有设置,shell到哪里获取它们的环境变量呢? 有些shell脚本时通过启动一个子shell来执行的(参见第五章) 。 子shell可以继承父shell导出过的变量。
举例来说,如果父shell是登录shell, 在/etc/profile、/etc/profile.d/*.sh 和 $HOME/.bashrc文件中设置并导出了变量,用户执行脚本的子shell就能够继承这些变量。
但记住:由父shell设置但并未导出的变量都是局部变量。子shell无法继承局部变量。
对于那些不启动子shell的脚本,变量已经存在于当前shell中了。所以就算没有设置BASH_ENV,也可以使用当前shell的局部变量和全局变量。
最好是在/etc/profile.d目录中创建一个以 .sh 结尾的文件。把所有新的或修改过的全局环境变量设置放在这个文件中。
大多数发行版中,存储个人用户永久性bash shell变量的地方是 $HOME/.bashrc 文件。这一点适用于所有类型的shell进程。但如果设置了BASH_ENV 变量,那么记住,除非它指向的是$HOME/.bashrc,否则你应该将非交互式shell的用户变量放在别的地方。
第五章中讲过的alias 命令设置就是不能持久的。你可以把自己的alias设置在$HOME/.bashrc启动文件中,使其效果持久化。
环境变量
6.1 什么是环境变量
Bash shell用一个叫作环境变量的特性来存储有关shell 会话和工作环境的信息。在bash shell中,环境变量分为两类:
全局变量
局部变量
本节将描述以上环境变量并演示怎么查看和使用它们。
全局环境变量对于shell会话和所有生成的子shell都是可见的。局部变量则只针对创建他们的shell可见。
Linux 系统在你开始bash会话时就设置了一些全局环境变量,系统环境变量基本上都是用大写字母,以区别于普通用户的环境变量。
6.1.1 全局环境变量
查看全局变量使用env 或者 printenv命令[root@centos1 ~]# printenv HOSTNAME=centos1 SELINUX_ROLE_REQUESTED= TERM=xterm SHELL=/bin/bash HADOOP_HOME=/home/hadoop HISTSIZE=1000 SSH_CLIENT=192.168.20.110 53812 22 SELINUX_USE_CURRENT_RANGE= QTDIR=/usr/lib64/qt-3.3 QTINC=/usr/lib64/qt-3.3/include SSH_TTY=/dev/pts/0 ... [root@centos1 ~]# env HOSTNAME=centos1 SELINUX_ROLE_REQUESTED= TERM=xterm SHELL=/bin/bash HADOOP_HOME=/home/hadoop HISTSIZE=1000 SSH_CLIENT=192.168.20.110 53812 22 SELINUX_USE_CURRENT_RANGE= QTDIR=/usr/lib64/qt-3.3 QTINC=/usr/lib64/qt-3.3/include SSH_TTY=/dev/pts/0 ...
登录方式也会影响到所设置的环境变量
[root@centos1 ~]# printenv HOME /root [root@centos1 ~]# env HOME env: HOME: No such file or directory [root@centos1 ~]# echo $HOME /root [root@centos1 ~]# #
要显示个别环境变量的值,可以使用printenv命令,但是不要使用env命令。
也可以使用echo显示环境变量额值。在这种情况下引用某个环境变量的时候必须在变量前面加上美元符($)。
在echo 命令中,在变量名钱加上$可不仅仅是要显示变量当前的值。它能够让变量作为命令行参数。
[root@centos1 ~]# ls $HOME anaconda-ks.cfg Documents hadoop-2.7.1.tar.gz install.log.syslog Pictures Templates Desktop Downloads install.log Music Public Videos
正如前面提到的,全局变量可作用于进程的所有子shell。
[root@centos1 ~]# bash [root@centos1 ~]# ps -f UID PID PPID C STIME TTY TIME CMD root 2317 2313 0 22:51 pts/0 00:00:00 -bash root 2351 2317 0 22:57 pts/0 00:00:00 bash root 2360 2351 9 22:57 pts/0 00:00:00 ps -f [root@centos1 ~]# echo $HOME /root [root@centos1 ~]# exit exit [root@centos1 ~]#
6.1.2 局部环境变量
局部环境变量只能在定义它们的进程中可见。实际上,Linux系统默认也定义了标准的局部环境变量。不过你也可以定义自己的局部变量,这些变量成为用户定义局部变量查看局部环境变量的列表有点复杂,没有一个只显示局部环境变量的命令。set 命令会显示某个特定进程设置的所有环境变量,包括局部变量,全局变量,以及用户定义变量。
[root@centos1 ~]# set BASH=/bin/bash BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=() BASH_CMDS=() BASH_LINENO=() BASH_SOURCE=() ...
env、printenv和set 之间差异很细微。set命令会显示出全局变量、局部变量及用户自定义变量,它还会按照字母顺序对结果进行排序。env、printenv 命令与set命令区别在于前两个命令不会对变量排序,也不会输出局部变量及用户自定义变量。
6.2 设置用户定义变量
本节将介绍在交互式shell中或者shell脚本中创建自己的变量并引用它们。6.2.1 设置局部用户定义变量
一旦启动一个bash shell(或者执行一个shell脚本),就能创建在这个shell进程内可见的局部变量。可以通过等号给环境变量赋值,值可以是数值或字符串。[root@centos1 ~]# echo $my_variable [root@centos1 ~]# my_variable=HELLO [root@centos1 ~]# echo $my_variable HELLO
设置用户自定义变量非常简单,如果给变量赋值一个含有空格的字符串值,必须用引号界定字符串的首和尾。
[root@centos1 ~]# echo $my_variable HELLO [root@centos1 ~]# my_variable="Hello World" [root@centos1 ~]# echo $my_variable Hello World [root@centos1 ~]# my_variable='Hello World' [root@centos1 ~]# echo $my_variable Hello World
如果没有引号的话,bash shell 会以为下一个词是一个要执行的命令。
敲门:所有环境变量名均使用大写字母,这是bash shell 的标准惯例,如果是你自己创建的局部变量或是shell脚本,请使用小写字母。变量名区分大小写。在涉及用户自定义的局部变量时坚持使用小写字母,这能够避免重新定义系统环境变量可能带来的灾难。
记住,变量名、等号和值之间没有空格,这一点非常重要,如果在赋值表达式中加上了空格 bash shell就会把值当成一个单独的命令。
设置了局部环境变量后,就能在shell进程的任何地方使用它了。但是如果生成了另外一个shell ,它在子shell中就不可用。
[root@centos1 ~]# my_variable='Hello World' [root@centos1 ~]# echo $my_variable Hello World [root@centos1 ~]# bash [root@centos1 ~]# echo $my_variable [root@centos1 ~]# exit exit [root@centos1 ~]# echo $my_variable Hello World [root@centos1 ~]#
当你退出了子进程,那个局部环境变量就依然可用。
类似的,如果在子进程中设置了一个局部变量,那么一旦你退出了子进程,那个局部环境变量就不能用了。
[root@centos1 ~]# echo $my_child [root@centos1 ~]# bash [root@centos1 ~]# my_child="Hello Little World" [root@centos1 ~]# echo $my_child Hello Little World [root@centos1 ~]# exit exit [root@centos1 ~]# echo $my_child
当我们回到父shell时,子shell 中设置的局部变量就不存在了。可以通过将局部的用户定义变量编程全局变量来改变这种情况。
6.2.2 设置全局环境变量
在设置全局环境变量的进程锁创建的子进程中,该变量都是可见的。创建全局环境变量的方法是先创建一个局部环境变量,然后再把它导出到全局环境中。这个过程可以通过export 命令来完成,变量名前不需加 $ 。
[root@centos1 ~]# echo $my_variable Hello World [root@centos1 ~]# export my_variable [root@centos1 ~]# echo $my_variable Hello World [root@centos1 ~]# bash [root@centos1 ~]# echo $my_variable Hello World [root@centos1 ~]# exit exit [root@centos1 ~]# echo $my_variable Hello World [root@centos1 ~]#
定义并导入局部环境变量my_variable 后,bash命令启动了一个子shell,在这个子shell中能够显示出变量my_variable的值。该变量能够保留它的值是应为export命令使其变成了全局变量。
修改子shell中的全局变量并不会影响到父shell中该变量的值。
[root@centos1 ~]# my_variable="I an Global now" [root@centos1 ~]# export my_variable [root@centos1 ~]# echo $my_variable I an Global now [root@centos1 ~]# bash [root@centos1 ~]# echo $my_variable I an Global now [root@centos1 ~]# my_variable="Null" [root@centos1 ~]# echo $my_variable Null [root@centos1 ~]# exit exit [root@centos1 ~]# echo $my_variable I an Global now
子shell 甚至无法使用export 命令改变父shell中全局变量的值。
[root@centos1 ~]# my_variable="I an Global now" [root@centos1 ~]# export my_variable [root@centos1 ~]# echo $my_variable I an Global now [root@centos1 ~]# bash [root@centos1 ~]# echo $my_variable I an Global now [root@centos1 ~]# my_variable="Null" [root@centos1 ~]# export my_variable [root@centos1 ~]# echo $my_variable Null [root@centos1 ~]# exit exit [root@centos1 ~]# echo $my_variable I an Global now
尽管子shell重新定义并导出了变量my_variable,但父shell中的my_variable变量依然保留着原先的值。
6.3 删除环境变量
删除已存在的环境变量,可以用 unset 命令完成这个操作。在unset命令中引用环境变量时,记住不要使用$。[root@centos1 ~]# echo $my_variable I an Global now [root@centos1 ~]# unset my_variable [root@centos1 ~]# echo $my_variable
窍门:在涉及环境变量名时,什么时候该使用$,什么时候不该使用$,如果用到变量,使用$ ; 如果要操作变量,不使用$ 。 这条规则有一个意外就是使用 printenv 显示某个变量的值时。
如果你再子进程中删除了一个全局环境变量,这只对子进程有效。该全局变量在父进程中依然可用。
和修改变量一样,在子shell中删除环境变量后,你无法将效果反映到父shell中。
6.4 默认的 shell 环境变量
默认情况下,bash shell 会用一些特定的环境变量来定义系统环境。这些变量在你的Linux系统上都是已经设置好了。只管放心使用。bash shell 源自当初的Uinx Bourne shell 因此保留了环境变量出了默认的Bourne的环境变量,bash shell 还提供了一些自有的变量。
并不是所有的默认环境变量都会在运行set 命令时列出,尽管这些都是默认的环境变量,但并不是每一个都必须有一个值。
6.5 设置Path 环境变量
当你再shell命令行中输入一个外部命令时,shell 必须搜索系统来找对应的程序。PATH 环境变量定义了用于进行命令和程序查找的目录。本书使用的是Ubuntu 系统,PATH环境变量内容是这样的:[root@centos1 ~]# echo $PATH /usr/local/jdk8/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin: /usr/sbin:/usr/bin:/home/hadoop/sbin:/home/hadoop/bin:/root/bin
PATH 中的目录使用冒号分隔。
如果命令或者程序的位置没有包括在PATH 变量中,那么如果不使用绝对路径,shell是没法找到的。如果shell找不到指定命令或者程序,它会产生一个错误信息:
[root@centos1 ~]# abc -bash: abc: command not found
可以把新的搜索目录添加到现有的PATH环境变量中,无需从头定义。PATH中各个目录之间使用冒号分隔的,你只需要引用原来的PATH 值,然后再给这个字符串添加新的目录进行了。可以考虑一面的例子。
[root@centos1 ~]# echo $PATH usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/home/hadoop/sbin:/home/hadoop/bin:/root/bin [root@centos1 ~]# PATH=$PATH:/usr/local/jdk8/bin/ [root@centos1 ~]# echo $PATH /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/home/hadoop/sbin:/home/hadoop/bin:/root/bin:/usr/local/jdk8/bin [root@centos1 ~]# java -version java version "1.8.0_111" Java(TM) SE Runtime Environment (build 1.8.0_111-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
如果希望子shell 也能找到你的程序位置,一定要记得把修改后的PATH 环境变量导出
程序员通常办法是将单点符也加入PATH环境变量。该单点符代表当前目录
[root@centos1 ~]# PATH=$PATH:. [root@centos1 ~]# cd /usr/local/jdk8/bin/ [root@centos1 bin]# java -version java version "1.8.0_111" Java(TM) SE Runtime Environment (build 1.8.0_111-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
对PATH 变量的修改只能持续到退出或者重启系统。这种效果并不能一直持续。下节将介绍如果持久保持环境变量的修改效果。
6.6 定位系统环境变量
当你登入linux 启动一个bash shell 时,默认情况下bash 会在几个文件中查找命令,这些文件叫作启动文件或者环境文件。bash 检查启动文件取决于你启动bash shell的方式,启动bash shell有三种方式:登录时作为默认登录shell
作为非登录shell的交互式shell
作为运行脚本的非交互shell
6.1.1 登录shell
当你登录Linux系统时,bash shell 会作为登录shell启动。登录shell会从5个不同的启动文件里读取命令:/etc/profile
$HOME/.bash_profile
$HOME/.bashrc
$HOME/.bash_login
$HOME/.profile
/etc/profile 文件是系统上默认的bash shell的主启动文件。系统上的每个用户登录时都会执行这个启动文件。
另外4个启动文件是针对用户的,可根据个人需求定制
1./etc/profile文件
/etc/profile 文件是bash shell 默认的主启动文件,只要你登陆了Linux系统。bash就会执行/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=`id -u` UID=`id -ru` fi USER="`id -un`" LOGNAME=$USER MAIL="/var/spool/mail/$USER" fi # Path manipulation if [ "$EUID" = "0" ]; then pathmunge /sbin pathmunge /usr/sbin pathmunge /usr/local/sbin else pathmunge /usr/local/sbin after pathmunge /usr/sbin after pathmunge /sbin after fi HOSTNAME=`/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 ] && [ "`id -gn`" = "`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 2>&1 fi fi done unset i unset -f pathmunge
用到了一个特性 for 语句。它用来迭代/etc/profile.d 目录下的所有文件。(该语句在13节中详述) 这为Linux系统提供了一个放置特定应用程序启动文件的地方,当用户登录时,shell会执行这些文件, /etc/profile.d 目录下包含以下文件:
[root@centos1 bin]# ls -l /etc/profile.d/ total 72 -rw-r--r--. 1 root root 1150 Apr 12 2016 colorls.csh -rw-r--r--. 1 root root 1179 Apr 12 2016 colorls.sh -rw-r--r--. 1 root root 92 Nov 22 2013 cvs.csh -rw-r--r--. 1 root root 78 Nov 22 2013 cvs.sh -rw-r--r--. 1 root root 192 Jan 21 2016 glib2.csh -rw-r--r--. 1 root root 192 Jan 21 2016 glib2.sh -rw-r--r--. 1 root root 58 May 11 2016 gnome-ssh-askpass.csh -rw-r--r--. 1 root root 70 May 11 2016 gnome-ssh-askpass.sh -rw-r--r--. 1 root root 1745 May 12 2016 lang.csh -rw-r--r--. 1 root root 2706 May 12 2016 lang.sh -rw-r--r--. 1 root root 123 Jun 4 2014 less.csh -rw-r--r--. 1 root root 121 Jun 4 2014 less.sh -rw-r--r--. 1 root root 976 Sep 24 2011 qt.csh -rw-r--r--. 1 root root 912 Sep 24 2011 qt.sh -rw-r--r--. 1 root root 2142 Jul 24 2015 udisks-bash-completion.sh -rw-r--r--. 1 root root 105 Jul 24 2015 vim.csh -rw-r--r--. 1 root root 269 Jul 24 2015 vim.sh -rw-r--r--. 1 root root 169 May 20 2009 which2.sh
不难发现,有些文件与系统中的特定应用有关。大部分应用会创建两个启动文件:一个供bash shell使用(使用.sh扩展名),一个供c shell 使用(使用.csh扩展名)。
lang.csh 和 lang.sh 文件会尝试去判断系统上所采用的默认语言字符集,然后设置对应的LANG环境变量。
2.$HOME目录下的启动文件
剩下的启动文件都起着同一个作用:提供一个用户专属的启动文件来定义该用户所用到的环境变量。大多数Linux发行版只用这四个启动文件找那个的一到两个。
$HOME/.bash_profile
$HOME/.bashrc
$HOME/.bash_login
$HOME/.profile
注意,这四个文件都是以点号开头,这说明它们是隐藏文件(不会再通常的ls命令输出列表中出现)。它们位于用户的HOME目录下,所以每个用户都可以编辑这些文件并添加自己的环境变量,这些环境变量会在每次启动bash shell 会话时生效。
shell会按照以下顺序,运行第一个被找到的文件,余下的则被忽略:
$HOME/.bash_profile
$HOME/.bash_login
$HOME/.profile
这个列表并没有$HOME/.bashrc文件。这是因为该文件通常通过其他文件运行的。
CentOS Linux 系统中的.bash_profile 文件内容如下:
[root@centos1 bin]# cat ~/.bash_profile # .bash_profile # Get the aliases and functions if [ -f ~/.bashrc ]; then . ~/.bashrc fi # User specific environment and startup programs PATH=$PATH:$HOME/bin export PATH
.bash_profile启动文件会先去检查HOME目录中是不是还有一个叫.bashrc的启动文件。如果有的话,会先去执行启动文件里面的命令。
6.6.2 交互式shell进程
如果你的bash shell 不是登录系统时启动的(比如是在命令行提示符下敲入bash 时启动),那么你启动的shell叫作交互式shell 。交互式shell不会像登录shell一样运行,但它依然提供了命令提示符来输入命令。如果bash是作为交互式shell启动的,它就不会访问/etc/profile文件,只会检查用户HOME目录中的.bashrc文件
CentOS系统上,这个文件看起来如下:
[work@16-11-120 ~]$ cat .bashrc # .bashrc # Source global definitions if [ -f /etc/bashrc ]; then . /etc/bashrc fi # Uncomment the following line if you don't like systemctl's auto-paging feature: # export SYSTEMD_PAGER= # User specific aliases and functions
.bashrc文件有两个作用:一是查看/etc目录下通过的bashrc文件,而是为用户提供一个定制自己的命令别名(参看第五章)和 私有脚本函数 (将在第17章讲到) 的地方。
6.6.3 非交互式shell
最后一种shell是非交互式shell。系统执行shell脚本时 用的就是这种shell。不同的地方在于它没有命令提示符。当你在系统上运行脚本时,希望运行一些特定启动的命令。窍门:脚本能以不同的方式执行。只是其中的某一些方式能够启动子shell。你会在第11章中学习到shell不同的执行方式。
为了处理这种情况,bash shell 提供了BASH_ENV 环境变量。当shell启动一个非交互式shell进程时,它会检查这个环境变量来查看要执行的启动文件。如果有指定的文件,shell会执行该文件里的命令,这通常包括shell脚本变量设置。
在默认的CentOS中 这个环境变量在默认情况下并未设置。如果变量未设置,printenv 命令会返回CLI提示符:
[work@16-11-120 ~]$ printenv BASH_ENV [work@16-11-120 ~]$ [work@16-11-120 ~]$ echo $BASH_ENV [work@16-11-120 ~]$
那如果BASH_ENV 变量没有设置,shell到哪里获取它们的环境变量呢? 有些shell脚本时通过启动一个子shell来执行的(参见第五章) 。 子shell可以继承父shell导出过的变量。
举例来说,如果父shell是登录shell, 在/etc/profile、/etc/profile.d/*.sh 和 $HOME/.bashrc文件中设置并导出了变量,用户执行脚本的子shell就能够继承这些变量。
但记住:由父shell设置但并未导出的变量都是局部变量。子shell无法继承局部变量。
对于那些不启动子shell的脚本,变量已经存在于当前shell中了。所以就算没有设置BASH_ENV,也可以使用当前shell的局部变量和全局变量。
6.6.4 环境变量持久化
对于全局环境变量来说(Linux系统所有的用户都需要使用的变量),可能更秦翔宇将新的或修改过的变量设置放在/etc/profile文件中。但这可不是什么好主意,如果升级了使用的发行版,这个文件会跟着更新,之前定制过的变量设置就没有了。最好是在/etc/profile.d目录中创建一个以 .sh 结尾的文件。把所有新的或修改过的全局环境变量设置放在这个文件中。
大多数发行版中,存储个人用户永久性bash shell变量的地方是 $HOME/.bashrc 文件。这一点适用于所有类型的shell进程。但如果设置了BASH_ENV 变量,那么记住,除非它指向的是$HOME/.bashrc,否则你应该将非交互式shell的用户变量放在别的地方。
第五章中讲过的alias 命令设置就是不能持久的。你可以把自己的alias设置在$HOME/.bashrc启动文件中,使其效果持久化。
6.7 数组变量
相关文章推荐
- linux共享库位置配置(LD_LIBRARY_PATH环境变量 或者 更改/etc/ld.so.conf 或者 使用-R选项)
- linux共享库位置配置(LD_LIBRARY_PATH环境变量 或者 更改/etc/ld.so.conf 或者 使用-R选项)
- 使用c语言设置linux系统环境变量实例
- 第五部分 使用Linux环境变量
- Linux下通过crontab调度脚本时脚本所使用的环境变量问题
- linux共享库位置配置(LD_LIBRARY_PATH环境变量 或者 更改/etc/ld.so.conf 或者 使用-R选项)
- Linux 软件安装使用(8)PATH与环境变量
- 如何恢复linux的环境变量ubuntu中root用户没有办法使用命令
- linux共享库位置配置(LD_LIBRARY_PATH环境变量 或者 更改/etc/ld.so.conf 或者 使用-R选项)
- 如何恢复linux的环境变量ubuntu中root用户没有办法使用命令
- linux下环境变量的使用
- linux 中环境变量配置错误导致部分命令不能使用包括vi
- linux下使用source /etc/profile保存配置后,新的环境变量只能在一个终端里面有效
- Linux上安装配置使用Tomcat说明文档和JDK环境变量配置
- linux共享库位置配置(LD_LIBRARY_PATH环境变量 或者 更改/etc/ld.so.conf 或者 使用-R选项)
- bashrc文件中环境变量配置错误,导致linux无法正常使用的解决方案
- Linux上安装配置使用Tomcat说明文档和JDK环境变量配置
- Linux 系统编程中环境变量的使用
- linux共享库位置配置(LD_LIBRARY_PATH环境变量 或者 更改/etc/ld.so.conf 或者 使用-R选项)
- Linux从用户层到内核层系列 - TCP/IP协议栈部分系列8: 基础知识之 - Linux环境变量使用Tip