linux的环境变量详解

什么是环境变量?

如下,在shell中定义一个变量,这个变量会被这个shell的子shell或者当前这个shell的进程所继承。

首先,在当前的shell中定义了一个HOLIDAY变量,定义变量用key=value的形式,等号两边不可有空格,key常用大写,value可以选用引号括起来,但如果value中有空格或者特殊字符时一定要用引号。

[dpc@aliyun ~]$ HOLIDAY=happy
[dpc@aliyun ~]$ echo $HOLIDAY
happy

进入子shell,查看HOLIDAY的值,发现子shell中没有这个变量

[dpc@aliyun ~]$ sh
sh-4.2$ echo $HOLIDAY

退出子shell,回到原来的shell查看变量是存在的。

sh-4.2$ exit
exit
[dpc@aliyun ~]$ echo $HOLIDAY
happy

export将变量声明到所有的shell中,重新进入子shell,查看是否有变量HOLIDAY

[dpc@aliyun ~]$ export HOLIDAY
[dpc@aliyun ~]$ sh
sh-4.2$ echo $HOLIDAY
happy

现在我们可以看到HOLIDAY变量的值可以被打印。因为现在HOLIDAY已经成为环境变量(Environment variables),这个环境变量在当前shell中定义,并被所有子shell和进程继承。在被export之前,HOLIDAY变量只是一个shell变量,不是环境变量,其只在当前的shell下有效。其实shell变量就是一个局部变量,环境变量就是一个全局变量,直接声明的是一个局部变量,通过export命令声明的是一个全局变量。

如果要查看环境变量,可以使用printenvenvset这三个命令,前两个命令是等效的。

[dpc@aliyun ~]$ printenv
XDG_SESSION_ID=19590
HOSTNAME=aliyun
SHELL=/bin/bash
TERM=xterm
HISTSIZE=1000
SSH_CLIENT=113.87.184.183 3761 22
HOLIDAY=happy
SSH_TTY=/dev/pts/0
USER=dpc
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
MAIL=/var/spool/mail/root
PWD=/home/dpc
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
HOME=/home/dpc
SHLVL=2
LOGNAME=dpc
SSH_CONNECTION=113.87.186.183 3761 172.18.4.152 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
_=/usr/bin/printenv
OLDPWD=/root

printenvenvset的区别:

  • printenv可用于查看单个环境变量,此时和用echo查看环境变量是等效的

    [dpc@aliyun ~]$ printenv SHELL
    /bin/bash
    [dpc@aliyun ~]$ echo $SHELL
    /bin/bash
    
  • env可用于修改变量,printenvenv查看的环境变量是一样的

  • set可查看所有的shell变量

    [dpc@aliyun ~]$ printenv | wc -l
    23
    [dpc@aliyun ~]$ env | wc -l
    23
    [dpc@aliyun ~]$ set | wc -l
    57
    

一些常见的环境变量:

SHELL:用于解释当前输入的命令的shell,通常默认是bash,另一种常见的是sh

TERM:当前运行的终端类型,常见是xterm

USER:当前登录的用户

PWD:当前的工作目录

OLDPWD:前一次的工作目录,此变量用于使用cd -命令切换到前一次的工作目录

LS_COLORS:定义了ls命令输出的不同类型文件显示的颜色

MAIL:当前用户邮箱的路径

PATH:系统查找命令时的目录列表。当用户输入一个命令时,系统按顺序从该列表中的目录查找可执行的命令

LANG:当前的语言和本地化设置,通常是系统语言和字符编码

HOME:当前用户的家目录,root用户为/root,其它用户为/home/username

_:前一次执行的命令

除了环境变量,还有一些常见的shell变量。注意shell变量用echo $variable_name查看

  • BASHOPTS:当前bash被执行时使用的选项列表
  • BASH_VERSION:当前bash的版本
  • BASH_VERSINFO:当前bash的版本
  • COLUMNS:当前窗口用于打印输出的列数,改变终端窗口大小列数随之变化
  • DIRSTACK:当前pushdpopd命令可用的目录堆栈
  • HISTFILESIZE:可存储到文件的中最大历史命令行数
  • HISTSIZE:可存储到内存中的最大历史命令行数
  • HOSTNAME:本机的hostname
  • IFS:内部字段分隔符(Internal Field Separator),用于分隔命令行中的输入,默认是空格
  • PS1:主要的命令提示符,定义了启动一个shell会话时的每行开头的提示符。PS2用于定义当一个命令跨多行时进行辅助声明的提示符。
  • SHELLOPTS:可以用set命令设置的shell选项
  • UID:当前用户的UID

设置和取消变量

将环境变量降为shell变量

[dpc@aliyun ~]$ export -n HOLIDAY

此时HOLIDAY将不再为环境变量

[dpc@aliyun ~]$ printenv HOLIDAY

但是它仍为shell变量

[dpc@aliyun ~]$ set | grep HOLIDAY
HOLIDAY=happy

如果想完全取消变量,把环境变量和shell变量都取消掉,可以使用unset命令

[dpc@aliyun ~]$ unset HOLIDAY

可验证此时HOLIDAY变量已经不存在了

[dpc@aliyun ~]$ echo $HOLIDAY

登录shell与非登录shell

当我们启动一个shell时它会去读取配置文件,但是在不同的启动方式下,它读取的配置文文件也不同。

shell会话有四个概念:

  • 交互式(Interactive)
  • 非交互式(Non-Interactive)
  • 登录(Login)
  • 非登录(Non-Login)

交互式和非交互式好理解,我们在有GUI(图形界面)的linux的终端上输入命令或者通过xshell连接服务器后输入命令都是在交互式shell会话中执行。而我们在终端中运行某个shell脚本,此时这个shell脚本是在非交互式shell会话中执行的。由此也可知,一个终端会话可以是这两种的结合。

对于交互式shell和非交互式shell,它们的类型不影响我们执行命令时使用的环境变量。

对于登录(Login)和非登录(Non-Login),两者比较让人迷惑。

比如我们通过ssh登录一个需要验证的远程服务器时,我们此时的shell会话就是一个登录shell会话。

[dpc@aliyun ~]$ ssh root@120.77.1.1
root@120.77.1.1‘s password:

在我们输入密码后,登录到了shell,此时由登录shell进入了非登录shell。

登录shell就是我们还没有输入密码登录到这个shell,当进入非登录shell时,意味着我们已经验证过了当前用户的密码登录到了该用户的shell中。

最简单的判断登录还是非登录shell的方法是:在当前的shell中,输入echo $0, 查看结果。非登录shell的输出是bashsu,登录shell的输出是-bash-su

[root@aliyun ~]# echo $0
-bash
[root@aliyun ~]# su dpc
[dpc@aliyun root]$ echo $0
bash
[dpc@aliyun root]$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

上面我们首先以root用户登录了shell,此时为登录shell。然后切换到了dpc用户,此时为非登录shell,我们查看非登录shell时的环境变量,使用的仍然是root用户的环境变量。

再试下下面的一种情况

[root@aliyun ~]# su - dpc
Last login: Thu Sep 24 00:23:07 CST 2020 on pts/0
[dpc@aliyun ~]$ echo $PATH
/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dpc/.local/bin:/home/dpc/bin

我们会发现用su dpc切换用户时没有验证密码,进入了登录shell,使用的是原来的root用户的环境变量;用su - dpc切换用户时验证了密码,进入了非登录shell,使用的是dpc用户的环境变量。

以下三个命令是等效的,都可以进入非登录shell。

su - dpc
su -l dpc
su --login dpc

登录shell和非登录shell的环境变量有何不同呢?

登录shell执行脚本的顺序

  • 登录shell执行/etc/profile
  • /etc/profile执行/etc/profile.d目录下的脚本
  • 然后执行当前用户的 ~/.bash_profile
  • ~/.bash_profile执行当前用户的 ~/.bashrc
  • ~/.bashrc执行/etc/bashrc

非登录shell执行脚本的顺序

  • 非登录shell首先执行 ~/.bashrc
  • 然后~/.bashrc执行/etc/bashrc
  • /etc/bashrc 调用/etc/profile.d目录下的脚本

参考
[1] environment and shell

[2] printenv, env and set

[3] Linxu环境变量

[4] System Variables

[5] Difference Between Login Shell and Non-Login Shell

[6] Login Shell Non-Login Shell

[7] Interactive and non-interactive shell

[8] How To Read and Set Environmental and Shell Variables on a Linux VPS

linux的环境变量详解

上一篇:linux下使用jekins自动化部署项目


下一篇:XP系统挂载Linux NFS共享