我通过自制程序安装了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;
答案 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
条目已从foo
和bar
之间移动在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,它的作用是:
以伪代码的形式对此进行改写,它正在做的是:
对此有害的是,如果您手动配置PATH,可能是为了添加覆盖系统路径组件的组件。如果在您不期望它时调用path_helper,那么它将通过将系统范围的路径组件放在路径组件之前来撤消更改。
路径助手如何被意外调用?例如,它被/ etc / zshenv调用,每次启动zsh shell时调用它,无论是子shell,还是从emacs等其他app调用的zsh实例,或者其他什么。
我已将其作为OpenRadar bug report on path_helper更详细地编写。