Linux 命令行與 shell 腳本編程大全 6 使用 Linux 環(huán)境變量

Linux 環(huán)境變量能提升 shell 使用體驗
很多程序和腳本都通過環(huán)境變量獲取系統(tǒng)信息、存儲臨時數(shù)據(jù)和配置信息

更多精彩

6.1 什么是環(huán)境變量

  1. shell 中用來存儲有關(guān) shell 會話和工作環(huán)境的變量,被叫做 環(huán)境變量( Environment Variable )
  2. 環(huán)境變量 被存儲在內(nèi)存中,方便程序或在 shell 中運(yùn)行的腳本能輕松訪問
  3. shell 中的環(huán)境變量分為兩類
    • 全局環(huán)境變量
    • 局部環(huán)境變量

6.1.1 全局環(huán)境變量

  1. 全局環(huán)境變量 之所以被叫做 全局 ,是因為其對于 父 shell 和所有生成的 子 shell 會話都是可見的
    • 局部環(huán)境變量 只對創(chuàng)建它們的 shell 可見
  2. Linux 內(nèi)置了很多默認(rèn)的 全局環(huán)境變量 ,會在用戶登錄 shell 時依次加載,這種 全局環(huán)境變量 被叫做 系統(tǒng)環(huán)境變量
  3. 系統(tǒng)環(huán)境變量 基本上都是使用全大寫字母,用來區(qū)別用戶自行創(chuàng)建的環(huán)境變量

6.1.1.1 env 命令和 printenv 命令查看全局環(huán)境變量

  1. 使用 env 命令和 printenv 命令可以查看當(dāng)前系統(tǒng)的全局環(huán)境變量,如下圖

  2. printenv 命令和 env 命令的區(qū)別在于,printenv 命令可以查看單個變量,而 env 命令不行,如下圖

6.1.1.2 echo 命令查看全局環(huán)境變量

  1. 使用 echo 命令也可以查看單個變量的值,但語法稍微復(fù)雜一點(diǎn),需要在變量名稱前加一個美元符號 ,如下圖

6.1.1.3 全局環(huán)境變量的全局觀

  1. 前面說過,全局環(huán)境變量 之所以被叫做 全局 ,是因為在 父 shell子 shell 中都可以訪問,如下圖

6.1.2 局部環(huán)境變量

  1. 局部環(huán)境變量 只能在創(chuàng)建它們的會話中使用
  2. Linux 同樣內(nèi)置了很多默認(rèn)的 局部環(huán)境變量

6.1.2.1 set 命令查看局部環(huán)境變量

  1. Linux 沒有內(nèi)置專門用來查看 局部環(huán)境變量 的命令
  2. 使用 set 命令只是可以在執(zhí)行結(jié)果中順便看到 局部環(huán)境變量,如下圖
    • 除了 局部環(huán)境變量 ,還會顯示 全局環(huán)境變量 ,以及用戶自定義環(huán)境變量
    • 顯示結(jié)果是按字母排序的


6.2 設(shè)置用戶定義變量

6.2.1 設(shè)置局部用戶定義變量

  1. 定義局部用戶變量不需要使用任何命令,直接定義一個變量名,并通過等號賦值即可,如下圖
    • 定義變量并賦值后,可以使用 echo $variable 命令來顯示變量值
    • 如果變量值存在空格,就不能直接賦值,需要將變量值用雙引號包裹


6.2.1.1 設(shè)置變量的語法規(guī)范

  1. 需要注意的是 ,大部分編程語言中,在變量名、等號和值之間添加空格,被認(rèn)為是一種松散且美觀的編碼方式
  2. 但是在 shell 中,這一點(diǎn)行不通,shell 中采用的是盡量緊湊的編碼方式,變量名、等號和值之間不能有空格
  3. 但是的但是,這一個要點(diǎn),在 shell 中也沒有被徹底貫徹,就比如第 5 章中介紹到的 coproc 命令 ,如果要在使用 coproc 命令的同時自定義協(xié)程名稱,則需要使用 coproc coprocName { command; } 命令,花括號中的空格是必不可少的,否則是語法錯誤
  4. 我認(rèn)為,這可能跟編寫這些語法的大神們自身的風(fēng)格有關(guān),誰知道呢?

6.2.1.2 局部變量父子間無法通信

  1. 父 shell 中定義的局部變量,無法在 子 shell 中訪問,如下圖
    • echo 命令在 子 shell 中嘗試訪問在 父 shell 中定義的變量,得到的執(zhí)行結(jié)果是一行空白
  2. 相同的,在 子 shell 中定義的局部變量,也無法在 父 shell 中訪問,如下圖

6.2.2 export 命令設(shè)置全局環(huán)境變量

  1. 使用 export 命令并不能直接定義 全局環(huán)境變量
  2. 需要先定義一個 局部環(huán)境變量 ,再使用 export 命令將這個變量提升為 全局環(huán)境變量 ,如下圖
    • 父 shell 中定義的局部變量,使用 export 命令提升后,在 子 shell 中也能夠順利訪問
    • 需要注意的是 ,使用 export variable 命令時,變量名前面不需要在美元符號

6.2.2.1 自定義的全局變量在子 shell 中是只讀的

  1. 父 shell 定義的 全局環(huán)境變量 ,任何 子 shell 都可以訪問,但無法修改,如下圖
    • 父 shell 中定義變量并提升后,在 子 shell 中可以訪問
    • 子 shell 中對該變量進(jìn)行重新賦值并提升后,退出 子 shell ,在 父 shell

6.3 unset 命令刪除環(huán)境變量

  1. 使用 unset 命令可以刪除定義的環(huán)境變量,如下圖
    • 使用 unset variable 命令后,就無法使用 echo $variable 訪問到對應(yīng)變量,說明變量已經(jīng)被刪除

6.3.1 子 shell 無法刪除父 shell 定義的全局變量

  1. 在 6.2.2.1 節(jié)中提到,父 shell 中定義的全局變量,對于子 shell 是只讀的 ,所以 子 shell 自然也無法刪除 父 shell 定義的全局變量,如下圖
    • 子 shell 中刪除由 父 shell 定義的變量后,只是當(dāng)前 子 shell 無法再訪問該變量
    • 但退出當(dāng)前 子 shell 后,父 shell 依舊能夠順利訪問到該變量,說明該變量對于 子 shell 是只讀的

6.4 默認(rèn)的 shell 環(huán)境變量

  1. 默認(rèn)情況下,Linux 會提供一些特定的環(huán)境變量用于定義 系統(tǒng)環(huán)境變量
  2. bash shell 的部分 系統(tǒng)環(huán)境變量 ,繼承自 Unix Bourne shell ,例如 HOME 、PATH
  3. bash shell 自身也定義了很多 系統(tǒng)環(huán)境變量 ,例如 HISTSIZEBASH

6.5 設(shè)置 PATH 環(huán)境變量

  1. PATH 是一個很關(guān)鍵的 系統(tǒng)環(huán)境變量 ,它定義了 用于進(jìn)行命令和程序查找的目錄 ,如下圖
    • 在第 5 章介紹過 shell 命令分為 內(nèi)建命令外部命令
    • 我們之所以能直接使用 外部命令 ,就是因為在 PATH 中將存放 外部命令 的目錄進(jìn)行了指定
  2. PATH 中的不同目錄,使用分號進(jìn)行分隔
  3. 如果某個命令或程序的位置不包含在 PATH 指定的目錄中,則無法進(jìn)行全局調(diào)用

6.5.1 為 PATH 添加自定義目錄

  1. PATH 中的目錄默認(rèn)情況下都是系統(tǒng)預(yù)置的,一般就包括用于存放 外部命令/bin 、/usr/bin/sbin 、/usr/sbin 目錄
  2. 如果想要讓其他程序的命令也能夠全局訪問,例如安裝 JDK 環(huán)境后一般都需要配置環(huán)境變量
  3. 只需要使用 PATH=$PATH:customCommandDirectory 即可
    • 這句命令的意思就是為 PATH 變量追加一個自定義的命令目錄,相當(dāng)于其他語言中的 += 操作
  4. 不過這種直接在 shell 會話中執(zhí)行的添加操作,是一次性的 ,如果當(dāng)前會話退出,或系統(tǒng)重啟,這一次的配置操作也會隨之失效

6.6 定位系統(tǒng)環(huán)境變量

  1. 上一節(jié)介紹到為 PATH 添加自定義目錄,但實(shí)現(xiàn)的效果是一次性的
  2. 要了解如何讓自定義的環(huán)境變量持久化存在與系統(tǒng)中,需要先了解 shell 的三種啟動方式
    • 登錄式 shell :登錄時作為默認(rèn) shell 啟動
    • 交互式 shell :在當(dāng)前 shell 會話中通過 bash 命令或 zsh 命令啟動的各種類型 子 shell
    • 非交互式 shell :在當(dāng)前 shell 會話中通過腳本運(yùn)行的 shell

6.6.1 登錄式 shell

  1. 登錄 Linux 時,啟動的 shell 就叫做 登錄式 shell
  2. 當(dāng) 登錄式 shell 啟動時,首先會嘗試讀取以下 5 個不同的啟動文件

6.6.1.1 /etc/profile 文件的作用

  1. /etc/profile 文件作為 shell 默認(rèn)的主啟動文件,主要是在系統(tǒng)啟動時,做一些默認(rèn)操作
  2. 同時會在文件末尾掃描指定的目錄,用于加載可能存在的自定義啟動文件
  3. 例如在 CentOS 的 /etc/profile 中,末尾有如下一段代碼
    • 這段代碼的大概意思就是會掃描 /etc/profile.d 目錄下的所有 .sh 文件
    • 所以一般推薦將一些自定義的全局環(huán)境變量、啟動文件放置在該目錄下
    • 如果偷懶直接在 /etc/profile 文件中進(jìn)行自定義修改,在系統(tǒng)升級后,可能該文件會被重置,那么之前做的自定義修改也就失效了
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
  1. 不過在 macOS 的 /etc/profile 中,末尾沒有上述這段代碼,而是下面這段代碼
    • 在文件末尾有一個判斷,大概意思是說:如果當(dāng)前的 shell 類型是 bash shell ,則加載 bashrc 配置
    • 由于我的 macOS 環(huán)境下使用的是 zsh shell ,所以輸出 ${BASH-no} 的結(jié)果是 no ,那么 bashrc 配置自然也不會加載

6.6.1.2 存放在 $HOME 目錄下的用戶啟動文件

  1. $HOME 目錄其實(shí)指的就是用戶根目錄,這是一個默認(rèn)的 系統(tǒng)環(huán)境變量 ,如下圖
  2. 該目錄下的啟動文件作用都一樣,提供一個用戶專屬的啟動文件用于定義該用戶會用到的環(huán)境變量
  3. 一般情況下,Linux 系統(tǒng)中都不會內(nèi)置全部的這四個文件,通常只存在一到兩個
  4. 在 macOS 中的查詢結(jié)果,就只有兩個,如下圖


  5. 在 CentOS 中的查詢結(jié)果,也只有兩個,如下圖


  6. 會被 shell 直接掃描的文件只有 .bash_profile 、.bash_login 、.profile
    • 需要注意的是 ,掃描過程中,并不是三個文件都一定會被掃描到
    • 掃描的規(guī)則是,運(yùn)行第一個被找到的文件,其他的直接忽略
    • 這可能就是在上述兩個系統(tǒng)環(huán)境中都沒有找到 .bash_login.profile 文件的原因吧,我猜的
  7. .bashrc 文件不會被直接掃描的原因是因為該文件通常會被其他文件執(zhí)行
    • 在 CentOS 中被 .bash_profile 執(zhí)行
    • 在 macOS 中被 /etc/profile 執(zhí)行

6.6.2 交互式 shell 進(jìn)程

  1. 登錄式 shell 中通過對應(yīng)類型的 shell 命令啟動的 shell ,就叫做 交互式 shell
  2. 交互式 shell 啟動時,不會訪問 /etc/profile 文件,會直接訪問 $HOME/.bashrc 文件
    • 前提是這個 shell 的類型是 bash shell ,如果是其他 shell ,則訪問對應(yīng)類型 shell 的啟動文件
    • 例如前文中說到的 zsh shell ,就會訪問 $HOME/.zshrc 文件
  3. .bashrc 的作用如下
    1. 執(zhí)行 /etc 目錄下通用的 bashrc 文件
    2. 為用戶提供一個 自定義命令別名( alias ) ,以及 私有腳本函數(shù) 的位置

6.6.3 非交互式 shell

  1. 在當(dāng)前 shell 會話中通過腳本運(yùn)行的 shell 就叫做 非交互式 shell
  2. 非交互式 shell 在執(zhí)行時,不會直接去訪問任何的啟動文件,而是直接繼承當(dāng)前執(zhí)行環(huán)境的 系統(tǒng)環(huán)境變量 以及 全局環(huán)境變量
    • 子 shell父 shell 之間局部變量無法通信一樣
    • 非交互式 shell 也無法訪問 父 shell 中沒有被提升的局部變量

6.6.4 環(huán)境變量持久化

  1. 在前文的 6.6.1.1 節(jié)中就有提到,將自定義的全局環(huán)境變量放置在 /etc/profile 中不是一個好主意
  2. 而是應(yīng)該放置在 /etc/profile.d 中,該目錄是 CentOS 專門用來存放用戶自定義 .sh 啟動文件的位置
  3. $HOME/.bashrc 是存儲自定義 bash shell 變量的位置,如果要存放 zsh shell ,則需要使用 $HOME/.zshrc

6.7 數(shù)組變量

  1. 數(shù)組變量并不實(shí)用,就好像所有的編程語言都應(yīng)該擁有數(shù)組一樣,在 shell 中,它只是被支持,但不常用

6.7.1 數(shù)組變量的基本語法

  1. 要定義一個數(shù)組變量,只需要在等號后面將多個用空格分隔的值,使用括號包裹即可,如下圖
    • 下圖的運(yùn)行環(huán)境是 CentOS
    • 可以看到,同樣一句話,使用雙引號包裹,就是字符串,使用括號包裹就是數(shù)組,而且直接輸出的結(jié)果不一樣


  2. 實(shí)測發(fā)現(xiàn) macOS 輸出的結(jié)果和 CentOS 不一樣,畢竟 macOS 是基于 Unix 開發(fā),而不是 Linux ,如下圖
    • 在 macOS 中直接輸出數(shù)組,也可以得到和字符串一樣的輸出結(jié)果
    • 同時使用索引訪問數(shù)組成員時,第 0 位是空,第 1 位才有值


6.7.2 通過索引訪問數(shù)組成員

  1. 在上一節(jié)的第一個圖中,可以看到直接訪問數(shù)組的結(jié)果是默認(rèn)輸出第一個值
  2. 那么如果要訪問數(shù)組的其他成員,則需要使用索引,如下圖
    • 索引從 0 開始,而且不支持負(fù)值
    • 可以看到和上一節(jié)第二個圖中 macOS 的查詢效果差別很大
    • 花括號和變量名直接也需要是緊湊的,不能有空格

6.7.3 星號顯示數(shù)組所有成員

  1. 要實(shí)現(xiàn)和字符串一樣的輸出效果,可以在指定索引的位置使用一個星號,如下圖
    • 這一操作 macOS 也支持


6.7.4 修改數(shù)組指定索引的值

  1. 要修改數(shù)組指定索引的值,只需要直接為數(shù)組指定索引的成員賦值即可,如下圖
    • 一個索引只能只能一個值,不能指定多個值
    • 但可以通過雙引號將多個值標(biāo)記為普通字符串,就可以實(shí)現(xiàn)類似效果


6.7.5 unset 命令刪除數(shù)組指定索引的值

  1. 使用 unset 命令可以刪除數(shù)組指定索引的值,但這個刪除操作并不會更新數(shù)組的索引排序,如下圖
    • 可以看到,使用 unset mySigns[1] 后,之前位于該索引的值就不存在了
    • 但使用 echo ${mySigns[1]} 嘗試輸出后,得到的是一個空值,而不是之前位于索引 2 位置的值
    • 這一點(diǎn)就和其他編程語言不一樣,例如 Java 和 Javascript ,在這些語言中,如果索引 1 的值被刪掉,數(shù)組的索引排序?qū)?,再次訪問索引 1 時,會得到之前位于索引 2 的值


6.8 小結(jié)

  1. Linux 中的環(huán)境變量分為 全局環(huán)境變量局部環(huán)境變量
  2. 全局環(huán)境變量 可以在父子級之間訪問,但父級定義的 全局環(huán)境變量 對于子級來說是只讀的
  3. 局部環(huán)境變量 無法在父子級之間訪問,只能在定義該變量的會話中訪問
  4. PATH 是一個很關(guān)鍵的 全局環(huán)境變量 ,也叫 系統(tǒng)環(huán)境變量 ,其為 shell 執(zhí)行各種命令指定了搜索目錄
  5. PATH 支持自定義修改,可以將各種不是系統(tǒng)自帶的命令加入其中,從而實(shí)現(xiàn)命令的全局訪問
  6. shell 的啟動方式分為三種,分別是 登錄式 shell交互式 shell 、非交互 shell
  7. /etc/profile 是 shell 的主啟動文件,在 登錄式 shell 啟動時會被訪問
  8. .bashrc 是用于存放用戶自定義變量的持久化文件,在 登錄式 shell交互式 shell 啟動時會被訪問
  9. 環(huán)境變量數(shù)組 是一個即不好用,也不常用的特性
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容