Homebrew は OpenVPN のバイナリを PATH ではなく sbin に置く
このフォーミュラは OpenVPN デーモンを sbin の下にインストールし、macOS の標準 PATH にはそれが含まれません。プレフィックスを確認し、一つのファイルで解決を直します。
インストールは終わり、brew は openvpn があると言うのに、シェルは command not found と返す。バイナリは存在し、シェルが一度も教えられていないディレクトリに置かれているだけだ。Homebrew はデーモン系のバイナリをプレフィックスの sbin ディレクトリにリンクし、macOS の標準 PATH は通常 bin ディレクトリを含み、sbin は含まない。壊れているものは何もなく、再インストールしてもこの状態は変わらない。
シェルの設定ファイルを編集する前に、四つの確認でこの仕組みを裏づける。
このフォーミュラが実際にインストールするもの
openvpn のフォーミュラはコマンドラインのデーモンを構築するので、実行ファイルは bin ではなく sbin の下に置かれる。Homebrew はそのバイナリをプレフィックスの sbin ディレクトリにリンクするため、"$(brew --prefix)/sbin/openvpn" --version は動くのに裸の呼び出しは動かない。バージョン付きの Cellar ディレクトリにも複製があり、そのパスを起動ファイルに書くと、アップグレード後も古いビルドに固定されたままになる。
プレフィックスのシンボリックリンクが安定したパスだ。Cellar のパスはバージョン番号を含む実装の詳細にすぎない。
ファイルシステムではなく Homebrew に聞く
どのインストールがこのフォーミュラを所有しているかを知っているパッケージマネージャーから始め、command -v brew、brew --prefix、brew list --versions openvpn、brew --prefix openvpn の順に確認する。最後がパスを出力すればフォーミュラは存在し、問題は解決の一点に絞られる。何も出力しなければ、シェルは一度もインストールされていないパッケージを間違った場所で探しており、それは別の修正を要する別の問題だ。
一つのマシンに Homebrew が二つ入っている場合が最も効く場面で、応答する brew がインストールした brew とは限らない。
シェルが sbin を見られない理由
ログインシェルはシステムの既定値と起動ファイルが追加するものから PATH を組み立てる。Homebrew の bin はよく追加されるが sbin は通常追加されないため、デーモン以外のコマンドはすべて動く。command -v openvpn が何も返さず、プレフィックス付きのパスがバージョンを返すことが、二つのコマンドによる診断のすべてだ。ディレクトリに本当にリンクがあるかは ls -l "$(brew --prefix)/sbin/openvpn" で確かめる。
リンクの欠落は PATH エントリの欠落とは別の障害であり、シェルの設定ファイルを編集して直るのは片方だけだ。
パスは一度、一か所だけで直す
現在のシェルで手早く試すなら、eval "$(brew shellenv)" がインストール変数を設定し、両方のディレクトリを先頭に加える。恒久的に整えるなら、使っているログイン方式でシェルが読む唯一の起動ファイルに shellenv の行を書き、bash と zsh のファイルに export を散らさないことだ。
そのうえで新しいターミナルを開き、キャッシュされたシェルは古い PATH を報告し続けるので、バージョンの問い合わせをやり直す。
検出とサービスは分けて考える
バイナリを見つけることは VPN サービスを動かすこととは違う。openvpn を自動で起動すると、パッケージの検出が一切触れなかったプロファイル、資格情報、権限、ライフサイクルの要件が加わる。Tunnelblick は独自のエンジンも同梱しているので、いま表示したバージョンはアプリが使うバージョンと無関係かもしれない。
どの実行ファイルがバージョン出力を出したかを記録する。その一行が、次に二つのバージョンが食い違ったときの一時間を節約する。