Shell 在 MacOS 及 Linux 中的文件讀取順序git
Interactive login | Interactive non-login | Script | |
---|---|---|---|
/etc/zshenv |
A | A | A |
~/.zshenv |
B | B | B |
/etc/zprofile |
C | ||
~/.zprofile |
D | ||
/etc/zshrc |
E | C | |
~/.zshrc |
F | D | |
/etc/zlogin |
G | ||
~/.zlogin |
H | ||
~/.zlogout |
I | ||
/etc/zlogout |
J |
如文章首圖與上表所示, zsh
/ bash
/ sh
都有針對於 login
/ nologin
及 interactive
, non-interactive
的不一樣讀取順序. 主要分爲如下四種情形github
interactive - login
: 登陸遠程主機(e.g ssh
)interactive - non-login
: 打開一個新 terminal 或一個新建 terminal 窗口non-interactive - non-login
: 執行一個腳本所在的 sub-shell
就處於這種狀態(這種狀態下不能進行交互, 這種狀態也只存在於腳本執行的d短暫時間內)non-interactive - login
: 這種狀況不多見, 好比這種狀況 echo 'echo $-; shopt login_shell' | ssh localhost
特別值得強調的是, 在 MacOS 中, 若是咱們打開一個 terminal 或新開一個tab時, zsh 會將其做爲
login
對待. 固然, 在運行腳本所建立的sub-shell
中, 其狀態都是non-interactive
shell
/etc/zprofile
對 PATH 作的奇怪事情在 Mac 下有 /etc/zprofile
文件, 在這個文件中有這樣一段命令ubuntu
if [ -x /usr/libexec/path_helper ]; then
eval `/usr/libexec/path_helper -s`
fi
複製代碼
由首圖及上表可知, zsh 會在 ~/.zshenv
以後加載 /etc/zprofile
, 進而執行 /usr/libexec/path_helper
這個腳本, 根據這個 blog 的描述, 這個腳本工具會將變量 $PATH
的順序重排, 同時讀取 /etc/paths
與 /etc/manpaths
中的 path
. 順着這個思路, 若是咱們在 zshenv
中定義了 $PATH
, 那麼精心配好的順序無疑會被打亂.bash
由此咱們能夠得出一個結論: 變量 $PATH
的定義必須必須放在 /etc/zprofile
以後markdown
$PATH
因爲 MacOS
的特殊性(若是咱們打開一個 terminal
或新開一個 tab
時, zsh 會將其做爲 login
對待), 在開啓 MacVim 時, MacVim 讀取到的文件順序與 login - non-interactive
是相同的ssh
也就是說, MacVim 不會讀取 ~/.zshrc
, 會讀取 ~/.zprofile
, 那麼若是咱們須要在 MacVim 中得到正確的 $PATH
, 就必須將 $PATH
及一些其餘基本變量的設置 放在 ~/.zprofile
中工具
zsh
配置我使用的是 zsh
, 我以爲很是順手, 各類功能強大, 兼容主流平臺, 所以個人全部工做環境都會使用 zsh
. 因爲平時會使用 MacOS
與 Linux
, 並且想要將本身的一些個性化配置在不一樣環境下通用, 那麼就須要考慮下如何在 MacOS
, MacVim
, ssh remote
, Linux Desktop
下有統一的加載行爲.oop
通過考慮, 我目前的方案是:fetch
建立一個 init.zsh
腳本, 在其中有各類變量的定義, 包括 $PATH
. 在腳本開始進行加載的判斷(防止同一次啓動中重複加載次腳本)
if [ -z "$_INIT_ZSH_LOADED" ]; then
_INIT_ZSH_LOADED=1
else
return
fi
複製代碼
在 .zprofile
的開頭 source init.zsh
在 .zshrc
的開頭 source init.zsh
在 .zlogin
中使用想要顯示的交互信息(好比 neofetch
信息)
這裏附上個人 shell 配置倉庫, 供各位參考