這兩天幫一台舊機器升級開發環境,包含了 rvm,homebrew 等,在用 brew doctor 想確認一下有沒有什麼問題的時候,跳出了一個警告如下:
Warning: /usr/bin occurs before /usr/local/bin
This means that system-provided programs will be used instead of those
provided by Homebrew. The following tools exist at both paths:
    git
    git-cvsserver
    git-receive-pack
    git-shell
    git-upload-archive
    git-upload-pack
Consider setting your PATH so that /usr/local/bin
occurs before /usr/bin. Here is a one-liner:
    echo 'export PATH="/usr/local/bin:$PATH"' >> ~/.zshrc
簡單說就是在我的 PATH 環境變數中,/usr/local/bin 被放到 /usr/bin 之後,所以我另外安裝的新版工具不會被呼叫到,而是會執行到系統自己帶的舊版工具。
因為我用的是 zsh,所以來檢查一下 ~/.zshrc,雖然裡面有對 PATH 做設定,不過並沒有包含到 /usr/local/bin 和 /usr/bin 等路徑的設定。試著在 ~/.zshrc 檔案的一開頭加了一行 echo $PATH,發現在 ~/.zshrc 載入之前 PATH 就已經有值了…一定是在更早的地方就被設定了。
找了一下,zsh 載入設定檔的順序如下:(Source)
| 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 | 
而我沒有 /etc/zshenv,也沒有 ~/.zshenv,接下來的 /etc/zprofile 內容則是:
# system-wide environment settings for zsh(1)
if [ -x /usr/libexec/path_helper ]; then
	eval `/usr/libexec/path_helper -s`
fi
實際執行 /usr/libexec/path_helper 的輸出如下:
PATH="/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/bin"; export PATH;
MANPATH="/usr/share/man:/usr/local/share/man:/opt/X11/share/man:/Applications/Xcode.app/Contents/Developer/usr/share/man:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/share/man"; export MANPATH;
Bingo!找到是那邊設定造成問題了。
搜尋一下,path_helper 是 OSX 提供的工具,用來設定 PATH 和 MANPATH 兩個環境變數。它會先載入 /etc/paths 和 /etc/manpaths,然後再載入 /etc/paths.d 和 /etc/manpaths.d,而我的 /etc/paths.d 中,/usr/local/bin 被放到了最後一行,改到第一行之後就一切正常了。