OS X Mountain Lion:path_helper如何工作?

Gor*_*Gao 13 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;
Run Code Online (Sandbox Code Playgroud)

pnk*_*lix 11

我怀疑你的.bash_profile.bashrc正在添加 .rbenv/shims到你的PATH,并且path_helper在shell启动期间调用之前正在运行 .

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.
Run Code Online (Sandbox Code Playgroud)

这里的关键点是path_helper实用程序旨在将内容添加到现有PATH设置,而不是替换它们.(而实际上,它确实是在前面加上内容,不附加它们,重要的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;
Run Code Online (Sandbox Code Playgroud)

需要注意的是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;
Run Code Online (Sandbox Code Playgroud)

最后,给予信用到期的信用:虽然上面的所有命令序列都是我自己调查的结果,但我最初的灵感是path_helper在阅读这里的注释之后调查行为,其中指出path_helper重用PATH环境变量集由父进程.


alg*_*gal 9

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

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

  1. 读取文件/ etc/paths中的路径列表
  2. 在其上列出目录/etc/paths.d中文件中的路径列表
  3. 改变PATH变量以删除列表中的任何项目
  4. APPEND到列表中突变的PATH变量的值
  5. 将此列表另存为新PATH

要以伪代码的形式重新表述,它正在做的是:

  1. NEWPATH =读取(/ etc/paths)
  2. NEWPATH = $ NEWPATH +追加+读取(/etc/paths.d/*)
  3. PATH = $ PATH -minus- $ NEWPATH
  4. NEWPATH = $ NEWPATH +追加+ $ PATH
  5. PATH = $ NEWPATH

对此有害的是,如果您手动配置PATH,可能是为了添加覆盖系统路径组件的组件.如果在您不期望它时调用path_helper,那么它将通过将系统范围的路径组件放在路径组件之前来撤消更改.

路径助手怎么会被意外调用?例如,它被/ etc/zshenv调用,每次启动zsh shell时都会调用它,无论是子shell,还是从emacs等其他应用程序调用的zsh实例.

我已经将它作为关于path_helper的OpenRadar 错误报告更详细地编写了.

  • 在OS El Capitan中,`path_helper`在`/ etc/zprofile`而不是`/ etc/zshenv`中调用,我认为这更糟糕*.至少`/ etc/zshenv`是第一个来源的东西,所以你可以覆盖`〜/ .zshenv`中所有shell(交互式,非交互​​式)的`PATH`.但是因为`/ etc/zprofile`来源于`〜/ .zshenv`,如果你想要交互式和非交互式shell的相同`PATH`,你就不得不重复`〜/ .zshenv`中的修改. `〜/ .zprofile`. (2认同)