LoginSignup
shiro_usagi
@shiro_usagi (shiro usagi)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

apple純正のsh,zsh,bash用のダメダメなパスはどのファイルに記載ありますか?

MacOSX

問題発生

ruby2.5.8にしたのでダメそうなプログラムをvimからチェックしていたら何かがおかしい。

$ gem environment
RubyGems Environment:
  - RUBYGEMS VERSION: 2.7.6.2
  - RUBY VERSION: 2.5.8 (2020-03-31 patchlevel 224) [x86_64-darwin13]
(中略)
  - RUBY EXECUTABLE: /usr/local/stow/ruby/bin/ruby
  - EXECUTABLE DIRECTORY: /usr/local/stow/ruby/bin
(中略)
  - SHELL PATH:
     - /usr/local/stow/ruby/bin
     - /usr/local/stow/gettext-021/bin
     - /usr/local/bin
     - /usr/bin
     - /bin
     - /usr/sbin
     - /sbin
$ vim
(vimから :!ruby -v )
ruby 2.0.0p481 (2014-05-08 revision 45883) [universal.x86_64-darwin13]

Press ENTER or type command to continue

ruby 2.0.0で問題だ!

$ echo $PATH
/usr/local/stow/ruby/bin:/usr/local/stow/gettext-021/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/xxxxxxx/bin:/usr/local/sbin

シェルから echo $PATH すると問題がない。

$ vim
(vimから :!echo '$PATH' 実行)
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/stow/ruby/bin:/usr/local/stow/gettext-021/bin:/Users/xxxxxxx/bin:/usr/local/sbin

Press ENTER or type command to continue

なんだこれは!大問題だ!
vimから !echo $PATH 実行すると見える
「/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:」
たしか、これはapple純正のbashなダメダメなパスの書き方。
vimが/etcディレクトリ辺りのどこからか拾っているのだろう。
「/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin」と書かれていれば問題起きない。
ホームディレクトリに.bash_profileがあれば問題ないのかもしれない。
筆者はzsh使用。

質問 apple純正のbashなダメダメなパスはどのディレクトリにありますか?

自己解決

/etc に pathsファイルを見つけた。
sudo vim で編集し、/usr/local/binを一番上にして一応だが、解決した。
但しvimからみえる $PATH とシェルからみえる $PATH は異なっている。厳密には問題は残る。

$ vim
(vimから :!echo $PATH 実行)
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/stow/ruby/bin:/usr/local/stow/gettext-021/bin:(以下略)

Press ENTER or type command to continue

freeBSD などBSD系で /usr/local/bin を最後に書くミスはしてないと思う。appleのエンジニアのミスと思われる。

以上

0

2Answer

質問内容からは外れますが、 Vim から見える PATH (正確には Vim の :!cmd で実行したコマンドから見える PATH)が異なる点について書いておきます。

Vim で :!cmd を実行するとコマンドを実行するためにシェルが起動します。シェルの上の Vim の上でさらにシェルが起動する形です。 Zsh ならば起動するとき ~/.zshenv を読み込みます(ただし ~/.zshrc, ~/.zlogin, ~/.zprofile はシェルのモードが違うので読み込みません)。 ~/.zshenv の中で PATH を設定しているなら、それが反映されます。

0

Comments

  1. @shiro_usagi

    Questioner
    コメント有り難う御座います。

    bash環境におけるvimのターミナルでも問題がありました。
    今のMacはログインシェルをzshにしています。

    ~ $ bash --version
    GNU bash, バージョン 4.4.23(1)-release (x86_64-apple-darwin13.4.0)
    (中略)
    ~ $ echo $PATH
    /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/xxxxxxx/bin
    ~ $ vim --version
    VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Aug 18 2020 xxxxxxxx)
    macOS version
    Included patches: 1-1471
    system vimrc file: "$VIM/vimrc"
    user vimrc file: "$HOME/.vimrc"
    2nd user vimrc file: "~/.vim/vimrc"
    (中略)
    ~ $ vim

    /usr/local/stow/ruby/bin:/usr/local/stow/gettext-021/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/xxxxxxx/bin

    Press ENTER or type command to continue
    ~ $
  2. @shiro_usagi

    Questioner
    zshはユーザーログインシェルに使っています。
    ~ $ zsh --version
    zsh 5.8 (x86_64-apple-darwin13.4.0)
    ~ $ echo $PATH
    /usr/local/stow/ruby/bin:/usr/local/stow/gettext-021/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/xxxxxxx/bin
    ~ $ vim
    (!echo $PATH)
    /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/stow/ruby/bin:/usr/local/stow/gettext-021/bin:/Users/xxxxxxx/bin

    Press ENTER or type command to continue

    というわけで、vimターミナルが読み込む$PATHにはzshでもbashでも各々問題がある。
  3. @shiro_usagi

    Questioner
    この記事を書いた時から、~/.zshenvは用意しており、PATHも記事の通りです。
    vimは ~/.zshenv 読み込む仕様でしょうが、vimのターミナルに限って問題を起していると思います。
  4. なるほど。 vim が内部で起動するシェルは $SHELL (ログインシェルと同じ)ですから、 bash 環境から vim を起動しても :!cmd を実行すると ~/.zshenv が読み込まれます。

    ~/.zshenv で PATH の先頭に追記しているなら、 bash → vim →> :!echo $PATH のときと zsh → vim → :!echo $PATH のときで PATH の先頭部分が同じになるはずですが、そうなっていませんね

    ~/.zshenv で複雑な PATH 操作をしているのか、 vim の起動スクリプトで PATH を設定しているのか、他に原因があるのか……
  5. @shiro_usagi

    Questioner
    .zshenvに記載しているPATHは以下の通りです。

    export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:~/bin
    export PATH=/usr/local/stow/gettext-021/bin:$PATH
    export PATH=/usr/local/stow/ruby/bin:$PATH
  6. そう設定されていれば何度 ~/.zshenv を読み込んでも

    /usr/local/stow/ruby/bin:/usr/local/stow/gettext-021/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/xxxxxxx/bin

    になるはずですね。 bash → vim →> :!echo $PATH のときはそうなっているようです。 zsh → vim → :!echo $PATH でそうならない理由はすみませんが見当がつきません。
  7. @shiro_usagi

    Questioner
    念の為、ログインシェルに詳しくない人の為にも書いておきます。

    macのログインシェルをbashに切り替えて .bash_profile にPATHに文字列追加し、上記と同じチェックをするとPATH設定は一致します。(問題がない)

    Last login: Thu Aug 20 19:30:00 on ttys000
    ~ $ echo $PATH
    /usr/local/stow/ruby/bin:/usr/local/stow/gettext-021/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/xxxxxxx/bin
    ~ $ vim
    (!echo $PATH)
    /usr/local/stow/ruby/bin:/usr/local/stow/gettext-021/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/xxxxxxx/bin

    Press ENTER or type command to continue

    1)vimとvimターミナルの組み合わせで使う。
    2)且つ、ターミナル内部からコマンド発行が必須な人。

    この条件でリモートログインなどの仕事やネットワーク等の仕事はログインシェルはbashが無難かと思います。
    どちらのシェルでも環境変数のPATHをvim内部に取り込むだけでよい筈ですが、疑問の残るvimターミナルのプログラム仕様です。

ruby関連の知識がないのでご質問内容を正確に把握できていなければすみません。
コメントにてログインシェルがzshとのことですが、PATHの設定を\${ZDOTDIR:-\${HOME}}/.zshenvで行なっているようでしたら、期待したPATHにならないのは/usr/libexec/path_helperが原因かもしれません(詳細 man path_helper)。
macOS、zshのログインシェルの場合特に設定していなければおそらく(.zshenvより後に)/etc/zprofileがsourceされ その中で


eval `/usr/libexec/path_helper -s`

されるようになっています。(このpath_helperが追記でご指摘の/etc/pathsを読む)。
/etc/pathsを書き換えるのは少々強引ですが、他の対応策としては.zshenvで一旦 unsetopt global_rcs などで /etc/zprofile をスキップし、.zshrcなどでスキップした


# system-wide environment settings for zsh(1)
if [ -x /usr/libexec/path_helper ]; then
    eval `/usr/libexec/path_helper -s`
fi

を実行した後からPATHをお好きな順に設定する。などがあります。

こちらの記事が詳しいです。
(記事自体の趣旨はご質問と関係ありませんが、path_helperに関する手順が解説されているので載せておきます。)

(追記)
すみません、vimの中のターミナルというと起動するのはログインシェルではないのでしょうか?
(&shellの設定にはどうなっていますか? /(usr/local)/bin/zsh\ -lの様に-lオプションが入っていなければインタラクティブだがログインシェルでないzshが起動するのではないでしょうか?)

$ zsh (-i)
==> インタラクティブな非ログインシェルが起動

$ zsh -l
==> ログインシェルから(新たな)ログインシェルが起動

ログインシェル以外ですとデフォルトではzshenv以降(zprofile、zlogin)を読まないはず(path_helperを読まないはず?)ですね。
vimの中と外でPATHが違うとのことで、気になりました。

0

Comments

  1. すでにご説明した箇所もありますがもう一度まとめておきます。

    path_helper自体は(バイナリなので中身はよくわかりませんが)、macOS固有のPATH設定、付属コマンドのMANPATH(マニュアルのパス)などを設定するためのものらしく(bash zshなどBourne shell系向けの)-sオプションをつけると、


    PATH="/usr/bin:/...:/...";export PATH;
    MANPATH="/usr/share/...:/...";export MANPATH;


    の様なシェルのソースコードを出力します。これを文字列としてevalに渡してPATH等の設定がなされる仕組みです。これがユーザーの.zshenvより後に実行された結果、PATHが上書きされることがあります。なのでシェル起動時に読まれるファイルの順序に気を付ければ(path_helper以外に原因がなければ)問題ありません。

    zshで、global_rcsオプションを切っていない場合、
    (以下`.`から始まるものはシステムグローバルではなく各ユーザーの${ZDOTDIR:-${HOME}}などにあるファイルとお考えください。)

    /etc/zshenv -> .zshenv -> /etc/zprofile (macOSではここでpath_helperが呼ばれる) -> /etc/zshrc -> .zshrc -> /etc/zlogin -> .zlogin
    の順で各ファイルが存在すればsourceされていきます。いずれかのファイルでglobal_rcsオプションを切ると以後の/etc以下のファイルは自動では読まれませんので、今回の場合ユーザー側の設定ファイルで/etc/zprofileより先に読まれる唯一のファイル.zshenvでglobal_rcsを切り( setopt no_global_rcs、unsetopt global_rcs 等。)、より後のファイル.zshrc、.zprofile、.zlogin (あるいは手動でsource すればどんなファイルでもいいはずです。/etc/zprofile自体をここでsourceしてもいいでしょう。) 等で、先にpath_helperの箇所を実行した**後から**PATHを設定すれば、上書きされることなく設定できるはずです。あるいは.zshenvでPATHの設定をせず/etc/zprofileより後のファイルで設定すればglobal_rcsを気にせずに済むかもしれません。(が、ログインシェル、インタラクティブシェル以外では.zshenv以降を読まないので別途注意が必要です。)

    path_helper自体を完全にスキップしたり実行権限を外したりするのはどんな影響があるかわかりませんが私はおすすめはしません。
  2. @shiro_usagi

    Questioner
    .zshenv でglobal_rcsオプションを最上位の行にして切っても、以後の/etc以下のファイルは読まれているように見えました。
    というわけで、私のスキルでは path_helper の実行権限を外すほかなくお手上げです。
    /usr/libexec/path_helper -sを実行してPATH取得するアプリは一つも無いと思いたい。(^_^;A


    ```
    ~ $ echo $PATH
    /usr/local/stow/ruby/bin:/usr/local/stow/gettext-021/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/xxxxxxx/bin
    ~ $ vim

    /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/stow/ruby/bin:/usr/local/stow/gettext-021/bin:/Users/xxxxxx/bin

    Press ENTER or type command to continue
    ~ $ la /usr/libexec/path_helper
    -rwxr-xr-x 1 root wheel 15K 1 12 2019 /usr/libexec/path_helper
    ~ $ less .zshenv
    ~ $ echo $GLOBAL_RCS

    ~ $
    ```
  3. /etc/zprofile以外では/etc/profile、/etc/csh.loginなどzsh以外のシェル用の設定ファイルに同様の記述がありますが、、

    ちなみに現在設定されているオプションはzshだと、
    $ setopt (引数なし)
    $ print -l -- ${(kv)options}

    などで一覧できるかと思います。

    $ print -- ${options[globalrcs]}
    ==> off

    の様に特定のオプションだけ調べることもできます。

  4. @shiro_usagi

    Questioner
    度々、有り難う御座います。勉強になります。

    $ print -l -- ${(kv)options} | ggrep -1 rcs
    off
    rcs
    on
    --
    on
    globalrcs
    off
    ~ $

Your answer might help someone💌