OS X Mountain Lion:path_helper如何工作?

时间:2012-09-13 15:03:29

标签: path osx-mountain-lion

我通过自制程序安装了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;

2 个答案:

答案 0 :(得分:10)

我怀疑您的.bash_profile.bashrc正在添加 .rbenv/shims到您的PATH,并且之前正在运行 在shell启动期间调用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设置,而不是替换它们。 (并在 现实,它真正做的是 prepend 内容,而不是追加它们, 这对PATH变量很重要......)

所以,如果我从PATH开始输入,则生成的设置 path_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/paths/etc/paths.d/*以及当前之后 PATH

后一个细节可能特别令人困惑,因为它可能导致 与原始PATH设置(!)相比的条目重新排序。

以下是此行为的一些示例:第一种情况显示正在删除重复的foo。第二个和第三个案例说明了条目重新排序:生成的PATH在两种情况下都是相同的,但在第三种情况下,/usr/bin条目已从foobar之间移动在PATH的前面。 (此重复条目删除似乎仅基于条目对上的简单字符串匹配,如下面的第四种情况所示,其中字符串/usr/bin/保持在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;

最后,在信用到期时给予信贷: 虽然上面的所有命令序列都是我自己调查的结果,但我最初的灵感是在阅读了注释here之后调查path_helper的行为, 它指出path_helper重用父进程设置的PATH环境变量。

答案 1 :(得分:9)

path_helper手册页不正确。手册页说path_helper将/etc/paths.d附加到PATH上。但实际上,path_helper将/etc/paths.d附加到/ etc / paths列表中,然后有效地将该结果预先发送到实际预先存在的PATH(以及清除该列表中重写的重复项的PATH)。

确切地说,例如,只讲PATH,它的作用是:

  1. 读取文件/ etc / paths
  2. 中的路径列表
  3. 在其上附上目录/etc/paths.d
  4. 中文件中的路径列表
  5. 改变PATH变量以删除列表中的任何项目
  6. APPEND到列表中变异PATH变量的值
  7. 将此列表另存为新PATH
  8. 以伪代码的形式对此进行改写,它正在做的是:

    1. NEWPATH =读取(/ etc / paths)
    2. NEWPATH = $ NEWPATH +追加+阅读(/etc/paths.d/*)
    3. PATH = $ PATH -minus- $ NEWPATH
    4. NEWPATH = $ NEWPATH +追加+ $ PATH
    5. PATH = $ NEWPATH
    6. 对此有害的是,如果您手动配置PATH,可能是为了添加覆盖系统路径组件的组件。如果在您不期望它时调用path_helper,那么它将通过将系统范围的路径组件放在路径组件之前来撤消更改。

      路径助手如何被意外调用?例如,它被/ etc / zshenv调用,每次启动zsh shell时调用它,无论是子shell,还是从emacs等其他app调用的zsh实例,或者其他什么。

      我已将其作为OpenRadar bug report on path_helper更详细地编写。