16

自作でrbenvをインストールしましたが、path_helperがパスの最初ではなく最後に〜/ .rbenv/shimsを配置した理由がわかりません。そして最も重要なのは、path_helperがこの情報をどのように取得したかということです。

path_helperのマニュアルページによると、/ etc/pathsおよび/etc/paths.d内のファイルからエントリを読み取ります。しかし、文字列「.rbenv/shims」が見つかりません。

~% cat /etc/paths 
/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/bin
~% ls -la /etc/paths.d 
total 0
drwxr-xr-x    2 root  wheel    68 Jun 21 03:16 .
drwxr-xr-x  107 root  wheel  3638 Sep 10 09:59 ..
~% /usr/libexec/path_helper
PATH="/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/gordon/.rbenv/shims"; export PATH;
4

2 に答える 2

14

.bash_profileまたは.bashrcがPATHに追加 されており、シェルの起動中に呼び出される.rbenv/shims前のある時点で実行されていると思わ れます。path_helper

path_helperのマニュアルページは次のように開きます。

 The path_helper utility reads the contents of the files in the directo-
 ries /etc/paths.d and /etc/manpaths.d and appends their contents to the
 PATH and MANPATH environment variables respectively.

ここで重要な点は、path_helperユーティリティは、コンテンツをPATH置き換えるのではなく、既存の設定にコンテンツを追加することを目的としているということです。(実際には、コンテンツを追加するのではなく、コンテンツを追加することです。これはPATH変数にとって重要です...)

したがって、のエントリから始める場合、PATHpath_helperによって生成された設定により、生成されたエントリが継続されるようにPATHなります。

% echo $SHELL
/bin/bash
% uname
Darwin
% /usr/libexec/path_helper 
PATH="/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"; export PATH;
% PATH="" /usr/libexec/path_helper 
PATH="/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin"; export PATH;
% PATH=foo /usr/libexec/path_helper 
PATH="/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:foo"; export PATH;

fooの内容は変更されていませんが、最後の行のPATHに含まれていることに注意してください。/etc/paths/etc/paths.d/*

同時に、path_helperユーティリティは、エントリが重複するパスを生成しないように注意しているようです。/etc/pathsand/etc/paths.d/*とcurrent を連結した後、重複するエントリを削除しますPATH

PATHこの後者の詳細は、元の設定(!)と比較してエントリの並べ替えを引き起こす可能性があるため、特に混乱を招く可能性があります。

この動作の例を次に示します。最初のケースは、重複fooが削除されていることを示しています。2番目と3番目のケースは、エントリの並べ替えを示しています。生成されたPATHはどちらの場合も同じですが、3番目のケースでは、/usr/binエントリはの間から前に移動されてfoobarますPATH。(この重複エントリの削除は、文字列がとの間に/usr/bin/残っている以下の4番目のケースで示されているように、エントリのペアでの単純な文字列照合に基づいているようです。)foo/bar

% PATH=foo:foo /usr/libexec/path_helper 
PATH="/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:foo"; export PATH;
% PATH=foo:bar /usr/libexec/path_helper 
PATH="/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:foo:bar"; export PATH;
% PATH=foo:/usr/bin:bar /usr/libexec/path_helper 
PATH="/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:foo:bar"; export PATH;
% PATH=foo/:/usr/bin/:bar /usr/libexec/path_helper 
PATH="/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:foo/:/usr/bin/:bar"; export PATH;

最後に、クレジットが必要な場所にクレジットを与えるために:上記のコマンドシーケンスはすべて私自身の調査の結果ですが、私はもともと、環境変数セットを再利用することを指摘したここpath_helperのメモを読んだ後の動作を調べるように促されました親プロセスによる。path_helperPATH

于 2012-12-31T12:23:56.043 に答える
11

path_helperのマニュアルページが正しくありません。マニュアルページには、path_helperが/etc/paths.dをPATHに追加していると書かれています。しかし実際には、path_helperは/etc/paths.dを/ etc / pathからリストに追加し、その結果を実際の既存のPATHに効果的に追加します(また、そのリストからオーバーライドされた重複のPATHを削除します)。

正確には、たとえばPATHについてのみ言えば、それが行うことは次のとおりです。

  1. ファイル/etc/paths内のパスのリストを読み取ります
  2. ディレクトリ/etc/paths.d内のファイル内のパスのリストをその上に追加します
  3. PATH変数を変更して、リスト内のアイテムを削除します
  4. 変更されたPATH変数の値をリストに追加します
  5. このリストを新しいPATHとして保存します

これを擬似コードで言い換えると、次のようになります。

  1. NEWPATH =読み取り(/ etc / path)
  2. NEWPATH = $ NEWPATH + append + Read(/etc/paths.d/*)
  3. PATH = $ PATH -minus- $ NEWPATH
  4. NEWPATH = $ NEWPATH + append + $ PATH
  5. PATH = $ NEWPATH

これについて危険なのは、PATHを手動で構成している場合、おそらくシステムパスコンポーネントをオーバーライドするコンポーネントを追加するためであるということです。予期しないときにpath_helperが呼び出された場合は、システム全体のパスコンポーネントをパスコンポーネントの前に配置することで、変更を元に戻します。

パスヘルパーはどのように予期せず呼び出されますか?たとえば、/ etc / zshenvによって呼び出されます。これは、サブシェルであろうと、emacsなどの別のアプリから呼び出されたzshインスタンスであろうと、zshシェルを起動するたびに呼び出されます。

path_helperのOpenRadarバグレポートとして、より詳細に記述しました。

于 2013-08-02T10:13:00.870 に答える