Zsh で .zshrc に書いた PATH や alias が反映されない
Zsh は起動の種類によって読む設定ファイルを変える。.zshrc は対話シェルだけ、.zprofile はログインシェルだけ、.zshenv はすべてのシェルで読まれる。
反映されない原因はほぼ、書いた場所とシェルの種類の食い違いである。
公開:
要約
.zshrc に書いた設定が効かないとき、内容が間違っているのではなく そのシェルが .zshrc を読んでいない ことがほとんどである。
Zsh は起動ファイルを 1 本に決めておらず、シェルの種類ごとに読む対象を変える。
公式ドキュメントの定義は次のとおりである。
.zshenv… すべての Zsh で読まれる(非対話・非ログインを含む).zprofile… ログインシェルのときだけ、.zshrcより前に読まれる.zshrc… 対話シェルのときだけ読まれる.zlogin… ログインシェルのときだけ、.zshrcより後に読まれる
それぞれの直前にシステム全体版(/etc/zshenv、/etc/zprofile、/etc/zshrc、/etc/zlogin)が読まれる点も重要で、PATH の順序が思ったとおりにならない場合はここが影響していることがある。
よくある原因
- Bash 用のファイルに書いている。
.bashrcや.bash_profileは Zsh からは読まれない。
ログインシェルを Zsh に切り替えた直後に起きやすい。 - 非対話シェルから実行している。
zsh -c 'コマンド'、cron、エディタのビルドタスクなどは対話シェルではないため.zshrcを読まない。
「ターミナルでは通るのに CI やエディタからは command not found」という形で表面化する。 ZDOTDIRが設定されている。
設定されている場合、Zsh は$HOMEではなく$ZDOTDIR配下の設定ファイルを読む。- 読み込みの後段で上書きされている。
ログインシェルではシステム側の起動ファイルが PATH を組み直すことがあり、.zshenvで先頭に置いたパスが後ろへ回る。
解決策
1. どのシェルなのかを確定する
[[ -o interactive ]] && echo interactive || echo non-interactive
[[ -o login ]] && echo login || echo non-login対話かつログインなら .zprofile → .zshrc の順に読まれている。
非対話なら .zshenv しか読まれていない。
2. 目的に応じて書く場所を選ぶ
# 対話操作のための設定(alias・プロンプト・補完)は .zshrc
echo 'alias ll="ls -la"' >> ~/.zshrc
# GUI アプリや非対話シェルにも渡したい環境変数は .zshenv
echo 'export EDITOR=vim' >> ~/.zshenvPATH は迷ったら .zshrc に書く。
非対話シェルでも必要な場合だけ .zshenv に置く。
3. 実際に読まれた順序を確かめる
zsh -x -i -c exit 2>&1 | head -40トレースに現れるファイル名が、そのシェルで実際に読まれたものである。
想定したファイルが出てこなければ、シェルの種類か ZDOTDIR を疑う。
4. 反映は再読み込みで行う
source ~/.zshrc編集は既に開いているシェルには自動で反映されない。source するか、新しいターミナルを開く。
5. PATH の最終結果を見る
echo $PATH | tr ':' '\n'
which -a python3意図した順序になっていなければ、.zshrc の末尾で明示的に組み直す。
Bash での同種の問題は Bash で PATH に追加したのに command not found が消えない にまとめてある。