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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM