MacでzshにおけるPATHの設定を正しく理解する

## rbenvでRubyのバージョンが切り替わらない
久々にRubyを触ろうと古に設定したrbenvを使ったんですが、rubyのバージョンが切り替えられない事態になっていました。bash利用時に設定したもので、zsh移行時に動かなくなっていたのだと思います。

```shell
$ which ruby
/usr/bin/ruby
```
rbenvを利用している場合、rubyのパスとしては`$HOME/.rbenv/shims/ruby`となるのが正しい動作です。

## rbenvの設定について
rbenvでは`rbenv init`を実行し`~/.rbenv/shims`をPATHに設定します。その時、`/usr/local/bin:/usr/bin:/bin`の前に来る必要があります。

```shell
$ echo $PATH
~/.rbenv/shims:/usr/local/bin:/usr/bin:/bin
#少なくともこの関係が必要。
```
自分の場合`/usr/local/bin:/usr/bin:/bin`の前ではなく、後ろに設定されていました。rbenvのコマンドは実行できるがrubyが切り替わらないのは、ここの設定が間違っているようです。

## 環境
- Mac : Catalina 10.15.7
- rbenv : 1.1.2

## export PATH="$PATH:xxx"で出来ないよ
zshに移行した際に「.zshenvにはPATHとかの設定を書くんだよ。」とどこかで見た昔の自分はzshenvにPATHの設定を書いていました。

```zsh:.zshenv
export PATH="$HOME/.rbenv/shims:$PATH"
```

この設定は必要ありませんが一応書いていたようです。しかし、実際は前には設定されていません。そもそも`/usr/local/bin`等の設定はどこで追加されたのでしょうか？

## zshの設定ファイルについて
zshの設定ファイルは以下です。番号順に設定ファイルが読み込まれます。
![zsh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123946/fb6e1670-dac4-1f03-8727-09c1a4c652d9.png)
図のA、B、Cは以下のの条件を満たす物を指し、起動時に設定ファイルを読み込む範囲です。

|  |ログインシェル  |インタラクティブシェル  |例 | 
|---|---|---|---|
|A  |○  |○  |Terminalの起動 |
|B  |×  |○  |zshコマンドでの起動 |
|C  |×  |×  |シェルスクリプト |

## /etc/zprofileのpath_helper
今回、.zshenvの後にPATHの設定がされてそうなので、/etc/zprofileの中を確認してみます。

```zsh:/etc/zprofile
# System-wide profile for interactive zsh(1) login shells.

# Setup user specific overrides for this in ~/.zprofile. See zshbuiltins(1)
# and zshoptions(1) for more details.

if [ -x /usr/libexec/path_helper ]; then
	eval `/usr/libexec/path_helper -s`
fi

```

どうやら`/usr/libexec/path_helper`がPATHの設定を行っているようです。実際に`/usr/libexec/path_helper -s`を実行すると以下のように出力されます。

```zsh
# 一部略
PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/xx/yy/zz"; export PATH;
MANPATH="/usr/share/man:/usr/local/share/man:/xx/yy/zz"; export MANPATH;
```

path_helperのマニュアルの説明を確認します。

```
DESCRIPTION
     The path_helper utility reads the contents of the files in the directories
     /etc/paths.d and /etc/manpaths.d and appends their contents to the PATH and MANPATH
     environment variables respectively.  (The MANPATH environment variable will not be
     modified unless it is already set in the environment.)

     Files in these directories should contain one path element per line.

     Prior to reading these directories, default PATH and MANPATH values are obtained from
     the files /etc/paths and /etc/manpaths respectively.
```

`/etc/paths`と`etc/path.d`が怪しそうです。

```text:/etc/paths
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
```
`/etc/paths`にパスの記載がありました。これがPATHとして設定されているようです。`/etc/paths.d/`にはアプリケーション毎にPATHの記載されたファイルが格納されていました。例えば自分の場合はWiresharkのファイルがあり、Wireshark.appへのパスが記載されていました。

## まとめ
今回、.zshenvでrbenvのパスの設定を行いました。しかし、.zshenvでPATHを設定してしまうと、ログインシェルの場合/etc/zprofileの設定が後からPATHを追加するという動作になるため、rbenvの設定が正しく行えていませんでした。
.zshrcに設定すると、rbenvで正しくrubyのバージョンが切り替えられるようになりました。実際、rbenvのgithubには`$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.zshrc`のように設定するコマンドが記載されています。
`/usr/local/bin`や`/usr/bin`がPATHの先頭に来てしまっても問題ない場合が多いですが、ツールによっては先にPATHを読み込む必要が出てきます。その時は正しい設定ファイルにPATHの設定をしてもらえればと思います。

## 参考
- https://qiita.com/muran001/items/7b104d33f5ea3f75353f
- https://qiita.com/gm_kou/items/24dec9f0e51b9343651b
- https://github.com/rbenv/rbenv