DEV Community

codemee
codemee

Posted on

shell 變數與環境變數

在 shell 中建立的變數可分為 shell 變數和環境變數, 兩者最簡單的區分就是:

  • shell 變數:只在當前 shell 下有效, 即使啟動子 shell, 這些變數也不會繼承到子 shell 中。
  • 環境 (environment )變數:會在當前 shell 以及子 shell 中生效。

以下我們個別說明。

shell 變數

首先來看 shell 變數:

$ SHELL_X=20
$ set | grep SHELL_X
SHELL_X=20
$ env | grep SHELL_X
$ bash
> set | grep SHELL_X
> env | grep SHELL_X
>
Enter fullscreen mode Exit fullscreen mode

建立變數的方式非常簡單, 就是:

變數名稱=變數內容
Enter fullscreen mode Exit fullscreen mode

要記得等號兩邊不要有空白, 變數內容如果有空白, 就要用雙引號括起來。這樣建立起來的變數是 shell 變數, 所以使用 set 列出所有變數時, 會看到 SHELL_X 出現在清單中, 但是用 env 列出環境變數時, 就不會出現了。

環境變數

建立環境變數的方式是使用 export 指令:

$ ENV_X=20
$ set | grep ENV_X
ENV_X=20
$ env | grep ENV_X
$ export ENV_X
$ env | grep ENV_X
ENV_X=20
$ bash
> set ENV_X
> set | grep ENV_X
ENV_X=20
_=ENV_X
> env | grep ENV_X
ENV_X=20
>
Enter fullscreen mode Exit fullscreen mode

你可以看到使用 exportENV_X 變成環境變數後, 不會是使用 set 還是 env 列出變數, 都會看到 ENV_X, 而且在啟動的子 shell 中, 仍然可以看到 ENV_X

利用設定檔設定環境變數

剛剛設定的環境變數在 shell 結束後就會消失, 如果想要讓 shell 執行起來後就會自動設定特定的環境變數, 在實際解說各種 shell 的設定檔前, 先來說明 shell 的模式:

  • login shell:如果需要輸入帳密認證才能啟動的 sehll 就是 login shell, 否則就不是 login shell。例如在當前 shell 下執行 zsh 或是 bash, 並不需要輸入帳密, 就不是 login shell。
  • interactive shell:有配置新的終端機的 shell 稱為 interactive shell, 例如以 shell 直接執行腳本時並不會配置新的終端機, 所以並不是 interactive shell。

是否為 login shell 或 interactive shell 會決定要採用哪些設定檔, 以下針對不同 shell 程式說明。

zsh

zsh 的設定檔執行順序如下:

  1. 不論是哪一種模式, 都會執行先執行 /etc/zshenv 檔, 例如我們將該檔案內容加上:

    echo "/etc/zshenv read."
    

    直接執行 zsh:

    $ zsh
    /etc/zshenv read.
    

    或是重新登入:

    /etc/zshenv read.
    
    $
    

    都會看到檔案中的 echo 顯示的 "/etc/zshenv read."。

  2. 每個 /etc 下的設定檔, 都有一個使用者私有的 . 版本, 所以每個 zsh 也都會執行在使用者家目錄下的 .zshenv 檔。如果在這個檔案裡面加入:

    echo ".zshenv read."
    

    不論是直接執行 zsh:

    $ zsh
    /etc/zshenv read.
    .zshenv read.
    
    $
    

    或是重新登入:

    /etc/zshenv read.
    .zshenv read.
    
    $
    

    都可以看到先執行 /etc/zshenv 接著執行.zshenv

  3. 若是 login shell, 會接著執行 /etc/zprofile, 以及 .zprofile 試著在該檔中個別加入對應的 echo 指令, 可以發現直接執行 bash 並不會執行這兩個設定檔:

    $ zsh
    /etc/zshenv read.
    .zshenv read.
    
    $    
    

    但如果是重新登入, 因為是 login shell, 所以會執行這兩個設定檔:

    /etc/zshenv read.
    .zshenv read.
    /etc/zprofile read.
    .zprofile read.
    
    $    
    
  4. 接著若是 interactive shell, 就會再執行 /etc/zshrc 以及 .zshrc 這一對檔案, 我們也利用同樣的方式加入 echo 指令測試。直接執行 zsh 結果如下:

    $ zsh
    /etc/zshenv read.
    .zshenv read.
    /etc/zshrc read.
    .zshrc read.
    
    $
    

    表示這是一個 interactive shell, 如果改成執行一個 shell 腳本:

    $ zsh hello.sh
    /etc/zshenv read.
    .zshenv read.
    hello
    
    $
    

    就不是 interactive shell, 也就不會執行 /etc/zshrc.zshrc 這對檔案了。

    重新登入則也會是 interactive shell:

    /etc/zshenv read.
    .zshenv read.
    /etc/zprofile read.
    .zprofile read.
    /etc/zshrc read.
    .zshrc read.
    
    $
    
  5. 如果是 login shell, 還會再執行 /etc/zloginzlogin 檔, 透過一樣的方式測試, 若直接執行 zsh

    $ zsh
    /etc/zshenv read.
    .zshenv read.
    /etc/zshrc read.
    .zshrc read.
    
    $
    

    改成重新登入就不一樣了:

    /etc/zshenv read.
    .zshenv read.
    /etc/zprofile read.
    .zprofile read.
    /etc/zshrc read.
    .zshrc read.
    /etc/zlogin read.
    .zlogin read.
    
    $
    

以上就是 zsh 執行個別設定檔的順序。

bash

bash 和 zsh 不大一樣, 詳細可參考這個圖解, 約略的順序如下:

  1. 如果不是 interactive shell, 就會執行 BASH_ENV 環境變數指定的檔案, 例如:

    $ set | grep BASH_ENV
    BASH_ENV=.non_interactive_shell
    $ cat .non_interactive_shell
    echo ".non_interactive_shell read."
    $ cat hello.sh
    echo hello
    $ bash hello.sh
    .non_interactive_shell read.
    hello
    $
    

    可以看到因為是執行腳本, 所以並不是 interactive shell, 會執行 BASH_ENV 環境變數指定的 .non_interactive_shell 檔。如果單純執行 bash

    $ bash
    $
    

    就不會執行 BASH_ENV 環境變數指定的 .non_interactive_shell

  2. 如果是 interactive shell, 但是 login shell, 就會先執行 /etc/profile, 然後再執行 .bash_profile.bash_login.profile 中第一個出現的檔案。

  3. 如果是 interactive shell 也不是 login shell, 就會執行 /etc/bash.bashrc 檔。

  4. 只要是 interactive shell, 最後還會執行 .bashrc 檔。

Top comments (0)