在 Mac OS X 中使用 zsh,環境變量 PATH 一不當心就會變得很紊亂,表現爲本身設置的路徑老是被放到系統路徑以後,部分路徑還會有重複。這是咱們不太瞭解 zsh 啓動時加載文件的順序和 Mac OS X 的 shell 類型致使的。linux
zsh 啓動過程當中會依次讀取如下文件:shell
login shell 是用戶登錄時,輸入用戶名和密碼後啓動的 shell,non-login shell 是登陸之後所打開的 shell。interactive shell 在終端上執行,shell 等待你的輸入,而且當即執行你提交的命令,跟用戶存在交互;non-interactive shell 以 shell script(非交互)方式執行。bash
interactive, login shell 比較常見,咱們 ssh 到遠程主機的字符終端時,就是典型的這類 shell。non-interactive, login shell 不多見,一些 X 設置會讓你登錄,目的僅僅是加載它的相應設置文件。interactive, non-login shell 一般發生在經過已存在的 session 啓動一個新的 shell,好比 linux 下的 screen、tmux,linux 下桌面環境啓動的 shell 也是這類 shell,好比 gnome shell。non-interactive, non-login shell 很常見,咱們執行 shell script 就是這類 shell。session
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
+--------------+-------------+-------------+-----------------+-----------------+ | | login | non-login | login | non-login | | | interactive | interactive | non-interactive | non-interactive | +--------------+-------------+-------------+-----------------+-----------------+ |/etc/zshenv | A | A | A | A | +--------------+-------------+-------------+-----------------+-----------------+ |~/.zshenv | B | B | B | B | +--------------+-------------+-------------+-----------------+-----------------+ |/etc/zprofile | C | | C | | +--------------+-------------+-------------+-----------------+-----------------+ |~/.zprofile | D | | D | | +--------------+-------------+-------------+-----------------+-----------------+ |/etc/zshrc | E | C | | | +--------------+-------------+-------------+-----------------+-----------------+ |~/.zshrc | F | D | | | +--------------+-------------+-------------+-----------------+-----------------+ |/etc/zlogin | G | | E | | +--------------+-------------+-------------+-----------------+-----------------+ |~/.zlogin | H | | F | | +--------------+-------------+-------------+-----------------+-----------------+ | | | | | | +--------------+-------------+-------------+-----------------+-----------------+ | | | | | | +--------------+-------------+-------------+-----------------+-----------------+ |~/.zlogout | I | | G | | +--------------+-------------+-------------+-----------------+-----------------+ |/etc/zlogout | J | | H | | +--------------+-------------+-------------+-----------------+-----------------+ |
那麼問題來了,在 Mac OS X 中打開 iTerm.app 或者 Terminal.app 啓動的 shell 是什麼類型呢?一般來講,應該是 interactive, non-login shell,但實際上倒是 interactive, login shell,至於爲何這樣就不深究了。下面的測試代碼能夠證實:app
1
2 |
[[ -o login ]] && echo 'yes' || echo 'no' [[ -o interactive ]] && echo 'yes' || echo 'no' |
因此,打開 iTerm.app 或者 Terminal.app 啓動的 shell 會讀取上述1-5中存在的全部文件,若是其中多個文件均對 PATH 環境變量做過設置,那麼最終呈現的 PATH 環境變量就會比較複雜,部分路徑重複也就不足爲奇了。查看 /etc/zshenv,會發現調用的是/usr/libexec/path_helper
,而它加載的正是系統路徑,而且將系統路徑放在最前。若是接下來用戶在 $ZDOTDIR 中的文件中加載了本身設置的路徑並置於最前,再接下來再加載的 /etc/zprofile、/etc/zshrc 可能還會調用/usr/libexec/path_helper
,又形成了系統路徑從新被放到最前面,造成了奇葩的 PATH 環境變量系統路徑、自設路徑、系統路徑交錯的現象。ssh
瞭解了這麼多,解決方法也很簡單,那就是上述1-5中僅讓必要的文件涉及 PATH 環境變量。好比在 /etc/zshenv 中經過調用/usr/libexec/path_helper
設置系統路徑,$ZDOTDIR/.zshenv 中將自設路徑放在最前,其他文件均不涉及 PATH 環境變量設置。測試
原文地址:https://www.jmlog.com/set-path-in-zsh-on-mac-os-x/spa