跟老男孩学Linux运维:Shell编程实战
上QQ阅读APP看书,第一时间看更新

3.2 环境变量

环境变量一般是指用export内置命令导出的变量,用于定义Shell的运行环境,保证Shell命令的正确执行。Shell通过环境变量来确定登录用户名、命令路径、终端类型、登录目录等,所有的环境变量都是系统全局变量,可用于所有子进程中,这包括编辑器、Shell脚本和各类应用。

环境变量可以在命令行中设置和创建,但用户退出命令行时这些变量值就会丢失,因此,如果希望永久保存环境变量,可在用户家目录下的.bash_profile或.bashrc(非用户登录模式特有,例如远程SSH)文件中,或者全局配置/etc/bashrc(非用户登录模式特有,例如远程SSH)或/etc/profile文件中定义。在将环境变量放入上述的文件中后,每次用户登录时这些变量都将被初始化。

按照系统规范,所有环境变量的名字均采用大写形式。在将环境变量应用于用户进程程序之前,都应该用export命令导出定义,例如:正确的环境变量定义方法为export OLDGIRL=1

有一些环境变量,比如HOME、PATH、SHELL、UID、USER等,在用户登录之前就已经被/bin/login程序设置好了。通常环境变量被定义并保存在用户家目录下的.bash_profile文件或全局的配置文件/etc/profile中,具体的环境变量说明参见表3-1。

表3-1 部分bash环境变量展示(执行env命令后获得)

(续)

在查看设置的变量时,有3个命令可以显示变量的值:set、env和declare(替代早期的typeset)。set命令输出所有的变量,包括全局变量和局部变量;env命令只显示全局变量;declare命令输出所有的变量、函数、整数和已经导出的变量。set -o命令显示bash Shell的所有参数配置信息。

范例3-1:set、env和declare输出。

        [root@oldboy ~]# env|tail
        SHLVL=1
        HOME=/root
        LOGNAME=root
        CVS_RSH=ssh
        MODULESHOME=/usr/share/Modules
        LESSOPEN=||/usr/bin/lesspipe.sh %s
        G_BROKEN_FILENAMES=1
        BASH_FUNC_module()=() {   eval `/usr/bin/modulecmd bash $*`
        }
        _=/bin/env
        [root@oldboy ~]# declare|tail
        _module_not_yet_loaded ()
        {
            comm -23 <(_module_avail|sort) <(tr : '\n' <<<${LOADEDMODULES}|sort)
        }
        module ()
        {
            eval `/usr/bin/modulecmd bash $*`
        }
        [root@oldboy ~]# set|tail
        _module_not_yet_loaded ()
        {
            comm -23 <(_module_avail|sort) <(tr : '\n' <<<${LOADEDMODULES}|sort)
        }
        module ()
        {
            eval `/usr/bin/modulecmd bash $*`
        }
        [root@oldboy ~]# set -o|head
        allexport         off
        braceexpand       on
        emacs             on
        errexit           off
        errtrace          off
        functrace         off
        hashall           on
        histexpand        on
        history           on
        ignoreeof         off

3.2.1 自定义环境变量

1.设置环境变量

如果想要设置环境变量,就要在给变量赋值之后或在设置变量时使用export命令,具体设置见下文的示例。其实,除了export命令,带-x选项的declare内置命令也可以完成同样的功能(注意:此处不要在变量名前面加$)。

export命令和declare命令的格式如下:

        ①export 变量名=value
        ②变量名=value ; export 变量名
        ③declare -x 变量名=value

提示:以上为设置环境变量的3种方法。

范例3-2:定义环境变量并赋值的方法。

        export NAME=oldboy
        declare -x NAME=oldboy
        NAME=oldboy ; export NAME

以下是自定义全局环境变量的示例:

        [root@oldboy script]# cat /etc/profile|grep OLD
        export OLDBOY='oldboy' #<==编辑/etc/profile,然后输出此行并保存
        [root@oldboy script]# source /etc/profile        #<==或./etc/profile使其生效
        [root@oldboy script]# echo $OLDBOY               #<==在变量前加$符号并打印变量值
        oldboy
        [root@oldboy script]# env|grep OLDBOY            #<==查看定义结果
        OLDBOY=oldboy

下面来看看让环境变量永久生效的常用设置文件。

(1)用户的环境变量配置

配置如下:

        [root@oldboy scripts]# ls /root/.bashrc         #<==推荐在此文件中优先设置
        /root/.bashrc
        [root@oldboy scripts]# ls /root/.bash_profile
        /root/.bash_profile

提示:对于用户的环境变量设置,比较常见的是用户家目录下的.bashrc和.bash_profile。

(2)全局环境变量的配置

常见的全局环境变量的配置文件如下:

        /etc/profile
        /etc/bashrc                                           #<==推荐在此文件中优先设置
        /etc/profile.d/

若要在登录后初始化或显示加载内容,则把脚本文件放在/etc/profile.d/下即可(无须加执行权限)。

2.设置登录提示的两种方式

第一种是在/etc/motd里增加提示的字符串,如下:

        [root@oldboy ~]# cat /etc/motd                    #<==文件里仅为字符串内容
        welcome to oldboy linux Shell training.

登录后显示内容如下:

        Last login : Fri Nov   7 15 :36 :56 2016 from 10.0.0.100
        welcome to oldboy linux Shell training.

第二种是在/etc/profile.d/下面增加如下脚本。

        [root@oldboy ~]# cat /etc/profile.d/oldboy.sh #<==这里是脚本的内容
        echo " Here is oldboy training "

登录后显示的内容如下:

        Last login : Fri Nov   7 15 :36 :56 2016 from 10.0.0.100
        Here is oldboy training

以下是在生产场景下(在Java环境中),自定义环境变量的示例。

        export JAVA_HOME=/application/jdk
        export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
        export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH:$HOME/bin
        export RESIN_HOME=/application/resin

提示:上述的环境变量设置通常放在/etc/profile全局环境变量里。

如果是写Java的脚本,那么最好是把上述Java环境配置放入脚本内重新定义,特别是作为定时任务执行的脚本。

3.2.2 显示与取消环境变量

1.通过echo或printf命令打印环境变量

下面我们先来看看常见的系统环境变量。

□$HOME:用户登录时进入的目录。

□$UID:当前用户的UID(用户标识),相当于id -u。

□$PWD:当前工作目录的绝对路径名。

□$SHELL:当前SHELL。

□$USER:当前用户。

......

范例3-3:通过echo和printf命令打印环境变量。

        [oldboy@oldboy ~]$ echo $HOME
        /home/oldboy
        [oldboy@oldboy ~]$ echo $UID
        504
        [oldboy@oldboy ~]$ echo $PWD
        /home/oldboy
        [oldboy@oldboy ~]$ echo $SHELL
        /bin/bash
        [oldboy@oldboy ~]$ echo $USER
        oldboy
        [root@oldboy ~]# printf "$HOME\n"
        #<==printf是一个更复杂的格式化打印内容的工具,一般不需要
        /root

提示:在写Shell脚本时可以直接使用系统默认的环境变量,一般情况下是不需要重新定义的,在使用定时任务等执行Shell脚本时建议在脚本中重新定义。

2.用env或set显示默认的环境变量

用env(printenv)显示默认环境变量的示例如下:

        [oldboy@oldboy ~]$ env
        HOSTNAME=oldboy
        SHELL=/bin/bash
        HISTSIZE=1000
        LC_ALL=C
        MAIL=/var/spool/mail/oldboy
        PATH=/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/oldboy/bin
        INPUTRC=/etc/inputrc
        PWD=/home/oldboy
        LANG=zh_cn.gb18030
        SHLVL=1
        HOME=/home/oldboy
        LOGNAME=oldboy
        中间和结尾省略若干代码

用set也可以显示环境变量(包括局部变量),如下:

        [root@oldboy ~]# set
        APACHEERR=hello
        BASH=/bin/bash
        BASH_ALIASES=()
        BASH_ARGC=()
        BASH_ARGV=()
        BASH_CMDS=()
        BASH_LINENO=()
        BASH_SOURCE=()
        BASH_VERSINFO=([0]="4" [1]="1" [2]="2" [3]="1" [4]="release" [5]="x86_64-redhat-
    linux-gnu")
        BASH_VERSION='4.1.2(1)-release'
        COLORS=/etc/DIR_COLORS
        COLUMNS=103
        中间和结尾省略若干代码

在3.2.1节还提到了一个相关的命令declare,大家还记得吗?

3.用unset消除本地变量和环境变量

用unset消除本地变量和环境变量的示例如下:

        [oldboy@oldboy ~]$ echo $USER
        oldboy
        [oldboy@oldboy ~]$ unset USER
        [oldboy@oldboy ~]$ echo $USER
                                              #<==此处为输出的空行

可以看到变量的内容显示为空。

环境变量的知识小结:

□变量名通常要大写。

□变量可以在自身的Shell及子Shell中使用。

□常用export来定义环境变量。

□执行env默认可以显示所有的环境变量名称及对应的值。

□输出时用“$变量名”,取消时用“unset变量名”。

□书写crond定时任务时要注意,脚本要用到的环境变量最好先在所执行的Shell脚本中重新定义。

□如果希望环境变量永久生效,则可以将其放在用户环境变量文件或全局环境变量文件里。

3.2.3 环境变量初始化与对应文件的生效顺序

在登录Linux系统并启动一个bash shell时,默认情况下bash会在若干个文件中查找环境变量的设置。这些文件可统称为系统环境文件。bash检查的环境变量文件的情况取决于系统运行Shell的方式。系统运行Shell的方式一般有3种:

1) 通过系统用户登录后默认运行的Shell。

2) 非登录交互式运行Shell。

3) 执行脚本运行非交互式Shell。

当用户登录Linux系统时,Shell会作为登录Shell启动。此时的登录Shell加载环境变量的顺序如图3-1所示。

图3-1 登录Shell读取环境变量文件的流程

用户登录系统后首先会加载/etc/profile全局环境变量文件,这是Linux系统上默认的Shell主环境变量文件。系统上每个用户登录都会加载这个文件。

当加载完/etc/profile文件后,才会执行/etc/profile.d目录下的脚本文件,这个目录下的脚本文件有很多,例如:系统的字符集设置(/etc/sysconfig/i18n)等,在后文开发跳板机案例里,我们也把脚本的起始加载放到这个目录下,以便用户登录后即刻运行脚本。

之后开始运行$HOME/.bash_profile(用户环境变量文件),在这个文件中,又会去找$HOME/.bashrc(用户环境变量文件),如果有,则执行,如果没有,则不执行。在$HOME/.bashrc文件中又会去找/etc/bashrc(全局环境变量文件),如果有,则执行,如果没有,则不执行。

如果用户的Shell不是登录时启动的(比如手动敲下bash时启动或者其他不需要输入密码的登录及远程SSH连接情况 ),那么这种非登录Shell只会加载$HOME/.bashrc (用户环境变量文件),并会去找/etc/bashrc(全局环境变量文件)。因此如果希望在非登录Shell下也可读到设置的环境变量等内容,就需要将变量设定等写入$HOME/.bashrc或者/etc/bashrc,而不是$HOME/.bash_profile或/etc/profile。