8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

xxenvとbash -lとPATH

Posted at

とっても便利なrbenv, ndenv, plenv, pyenvなどのxxenvシリーズでPATHにハマった記録。

TL; DR

  • xxenvの実装やバージョンによっては、PATHに~/.xxenv/shimsが2重に追加されないようになっている。
  • この時、bash -lでコマンドを実行すると1、引き継がれたPATHにshimsが含まれるので2度目の追加がされず、shimsの優先順位が/usr/binなどより低くなり、ビルトインのインタプリタに解決されて涙目になる。
  • ドキュメントでは~/.xxenv/binにPATHを通すように指示されているが、ついでに~/.xxenv/shimsに通しておくと確実か。

事の発端

$ which perl
/Users/shin/.plenv/shims/perl

$ bash -lc "which perl"
/usr/bin/perl

何故???

PATHを確認

echo $PATH | perl -nle 'print join("\n", split(":", $_))'

こんな感じのワンライナーで適当に目grep。

# echo $PATH
...
/Users/shin/.plenv/shims
/Users/shin/.plenv/bin
/Users/shin/bin
/usr/local/bin
/usr/local/bin
/usr/bin
...

# bash -lc "echo \$PATH"
...
/Users/shin/.plenv/bin
/Users/shin/bin
/usr/local/bin
/usr/local/bin
/usr/bin
...
/Users/shin/.plenv/shims
/Users/shin/.plenv/bin
/Users/shin/bin

確かに何かがおかしい模様。

なにをやっているか見てみる

頼れる味方-xオプション

$ bash -lxc "echo hoge"
+ '[' -x /usr/libexec/path_helper ']'
++ /usr/libexec/path_helper -s
+ eval 'PATH="/usr/local/bin:/usr/bin:...";' export 'PATH;'
++ PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:...
++ export PATH
+ '[' /bin/bash '!=' no ']'
+ '[' -r /etc/bashrc ']'
+ . /etc/bashrc
++ '[' -z '' ']'
++ return
# 以下.bash_profile

どうも.bash_profileの前に、path_helperなるものでPATHがゴニョゴニョされている様子。

そういえば、bashの設定の読み込み順がどうだったかというと...

bash が対話的なログインシェルとして起動されるか、 --login オプション付きの非対話的シェルとして起動されると、 /etc/profile ファイルが存在すれば、 bash はまずここからコマンドを読み込んで実行します。 このファイルを読んだ後、 bash は ~/.bash_profile, ~/.bash_login, ~/.profile をこの 順番で探します。 bash は、この中で最初に見つかり、かつ読み込みが可能であるファイルから コマンドを読み込んで実行します。 --noprofile オプションを使ってシェルを起動すれば、 この動作を行わないようにできます。
https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html

ということで/etc/profileを確認すると

# System-wide .profile for sh(1)

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

if [ "${BASH-no}" != "no" ]; then
        [ -r /etc/bashrc ] && . /etc/bashrc
fi

を発見。怪しい、怪しすぎる。

man path_helper

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.
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man8/path_helper.8.html

/etc/paths.d以下のファイルを読み込むらしいが、

$ ls /etc/paths.d/
40-XQuartz
$ cat /etc/paths.d/40-XQuartz
/opt/X11/bin

パット見では悪さをする雰囲気ではなさそう?

/usr/libexec/path_helper -s

とりあえずコレの挙動を確認。

$ /usr/libexec/path_helper -s
PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Users/shin/.go/bin:...:/Users/shin/.plenv/bin:/Users/shin/bin"; export PATH;

現在のPATHの前に/usr/local/binなどが、、、あれ、そもそもPATHに値入ってるのか。exportしているのだからそりゃそうか。

$ bash --noprofile -lc "echo \$PATH"
/Users/shin/.go/bin:...:/opt/X11/bin

あらためてPATHを見てみる。

$ bash -lc "echo \$PATH" | perl -nle 'print join("\n", split(":", $_))'
/Users/shin/.go/bin
/Users/shin/Documents/lab/go/bin
/usr/local/opt/httpd/sbin
/Users/shin/.pyenv/bin
/Users/shin/.ndenv/bin
/Users/shin/.rbenv/shims
/Users/shin/.rbenv/bin
/Users/shin/.plenv/bin
/Users/shin/bin
/usr/local/bin
/usr/local/bin # ここからpath_helper
/usr/bin
/bin
/usr/sbin
/sbin
/opt/X11/bin
...

path_helperより前の部分は.bash_profileとかで付与されたPATHのはず。
しかしどうもrbenv以外はshimsへのPATHが張られていない模様。

shimsへのPATHはeval $(xxenv init -)で追加されるはずなのだが、もしかすると既に張られているときは張らないような処理になっていると仮説を立ててみると...

# https://github.com/tokuhirom/plenv/blob/2.1.1/libexec/plenv-init#L76-L78
if [[ ":${PATH}:" != *:"${PLENV_ROOT}/shims":* ]]; then
  echo 'export PATH="'${PLENV_ROOT}'/shims:${PATH}"'
fi

見事に当たった様子。
ただ、この部分、v2.2.0になって変わっているようで、

# https://github.com/tokuhirom/plenv/blob/2.2.0/libexec/plenv-init#L84-L93
case "$shell" in
fish )
  echo "setenv PATH '${PLENV_ROOT}/shims' \$PATH"
  echo "setenv PLENV_SHELL $shell"
  ;;
* )
  echo 'export PATH="'${PLENV_ROOT}'/shims:${PATH}"'
  echo "export PLENV_SHELL=$shell"
  ;;
esac

チェック無くなっとるー。

ということで

plenvのバージョンを2.2.0に上げたところ、

$ bash -lc "which perl"
/Users/shin/.plenv/shims/perl

解決しましたとさ。 (path_helper疑ってゴメン)

全てのxxenvで、この辺りの微妙な挙動が揃っているとは限らないので、いっそbinと一緒にshimsへのパスも追加しておいたほうが無難かもしれない。

  1. bash -lc "ruby ..."のようにPATH設定を手抜くのはxxenvで良くあるテク。

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?