• 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

  • 相关阅读:
    codeforces 189A
    hdu 2085
    hdu 2083
    cf 1237 C2. Balanced Removals (Harder)
    cf 1244 D. Paint the Tree
    cf 1241 E. Paint the Tree(DP)
    cf 1241 D. Sequence Sorting(思维)
    cf1228 D Complete Tripartite(哈希)
    Windows10 与 WSL(Ubuntu)的文件互访
    Ubuntu下运行python文件
  • 原文地址:https://www.cnblogs.com/sincere-ye/p/13712724.html
Copyright © 2020-2023  润新知