発端
ある日突然、rspec-modeのテスト実行が失敗するようになった。
ログによるとシステムのrubyを使おうとしており、rbenvが無視されている。
rbenv.elはもちろん使っているし、exec-pathに~/.rbenv/shimsを入れるようにしてもダメ。exec-path-from-shellも使ってみたけどダメ。
犯人はpath_helper
弱り果ててrpsec-modeに直接デバッグコードを埋めて調べてみると、PATHの先頭に/usr/bin,/binなどが入っていて、rbenvのrubyよりもシステムのruby(/usr/bin/ruby)が優先されていた。
もちろんrbenvのパスはrbenv.elが先頭に追加しているはずなので、原因がよく分からなかったのだが、こちらなどを見て判明。
/etc/zshenvに以下のコード
# system-wide environment settings for zsh(1)
if [ -x /usr/libexec/path_helper ]; then
eval `/usr/libexec/path_helper -s`
fi
が書かれていて、書いてある通りにpath_helperを実行すると
$ /usr/libexec/path_helper -s
PATH="/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin(略)"
のように標準のpathが先頭について返ってくる。このpathは/etc/pathsに
/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/bin
のように記述されている。
回避策
さて、zshの設定ファイルが読み込まれる順番は以下の通り。
- /etc/zshenv
- ~/.zshenv
- /etc/zprofile (ログインシェルの場合)
- ~/.zprofile (ログインシェルの場合)
- /etc/zshrc (対話的シェルの場合)
- ~/.zshrc (対話的シェルの場合)
- /etc/zlogin (ログインシェルの場合)
- ~/.zlogin (ログインシェルの場合)
対話シェルではないので.zhsrcは使われず、/etc/zshenvだけが読み込まれた結果、先頭に/usr/binが追加されてしまっていたわけ。
というわけで回避策は
~/.zshenvにrbenvの設定を書く
でした。
rbenvの設定はいつも通り
export PATH=$HOME/.rbenv/bin:$PATH
eval "$(rbenv init - zsh)"
でOK。
補足
なお、.zshrcにもrbenvの設定が書いてある場合はPATHが重複してしまうので、気になる人は調整しましょう。
あるいはpath_helperを消す、/etc/zshenvをzprofileにリネームするなどの方法もあるけれど、なるべくシステムのファイルに手を加えない方が無難と思われます。(OSアップデートの時に戻ってしまったりするしね)
おまけ
なぜ突然この問題が表面化したのかは結局分からないまま。
.emacsをどこかいじった結果だと思われるが・・・