2012-09-13 19 views
10

Instalé rbenv a través de homebrew, y ahora no sé por qué path_helper puso ~/.rbenv/shims al final de la ruta en lugar de al principio. Y lo más importante, ¿cómo path_helper obtuvo esta información?OS X Mountain Lion: ¿cómo funciona path_helper?

De acuerdo con la página man de path_helper, lee las entradas de/etc/paths y de los archivos en /etc/paths.d. Pero no puedo encontrar la cadena ".rbenv/shims" allí.

~% 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; 

Respuesta

6

que sospecha que su .bash_profile o .bashrc es la adición de .rbenv/shims a su PATH, y que se está ejecutando en algún momento antes path_helper se invoca durante la cáscara de puesta en marcha.

La página del manual para path_helper abre con:

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. 

El punto crucial aquí es que la utilidad path_helper pretende añadir contenido a una configuración existente PATH, no las reemplaza. (Y en realidad, lo que realmente hace es anteponer contenidos, no añadirlos, que importa para PATH las variables ...)

lo tanto, si comienzo con una entrada en mi PATH, genera el ajuste por path_helper se asegurará de que la entrada continúe en el PATH que genera.

% 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; 

Tenga en cuenta que foo se ha incluido en mi camino en la última línea, a pesar de que el contenido de /etc/paths y /etc/paths.d/* no han cambiado.

Al mismo tiempo, la utilidad path_helper también parece tener cuidado, no , para generar rutas con entradas duplicadas; elimina las entradas duplicadas después de concatenar /etc/paths y /etc/paths.d/* y la actual PATH.

Este último detalle puede ser especialmente confuso, ya que puede causar el reordenamiento de entradas en comparación con el ajuste original PATH (!).

A continuación se muestran algunos ejemplos de este comportamiento: El primer caso muestra un duplicado de foo que se está eliminando. El segundo y tercer caso ilustran el reordenamiento de entrada: el PATH generado es el mismo en ambos casos, pero en el tercer caso, la entrada /usr/bin se ha movido de entre foo y bar al frente del PATH. (Esta eliminación de entrada duplicada parece basarse en una simple coincidencia de cadenas en los pares de entradas, como se ilustra en el cuarto caso a continuación, donde la cadena /usr/bin/ permanece entre foo/ y 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; 

Por último, para dar crédito a quien lo merece: Mientras que todas las secuencias de comandos anteriores son el resultado de mis propias investigaciones, me sentí inspirado originalmente para estudiar el comportamiento de path_helper después de leer la nota here , que señaló que path_helper reutiliza la variable de entorno PATH establecida por el proceso principal.

+1

Gracias por señalar que, en comparación con los documentos, path_helper * prepede * rutas y elimina duplicados. – algal

6

La página del manual path_helper es incorrecta. La página man dice que path_helper está añadiendo /etc/paths.d a la RUTA. Pero en realidad, path_helper está APLIENDO /etc/paths.d en la lista de/etc/paths y luego PREPENDE efectivamente ese resultado en PATH preexistente real (así como también purgando PATH de duplicados anulados de esa lista).

Para ser exactos, hablando sólo de PATH, por ejemplo, lo que hace es:

  1. leer la lista de rutas en el archivo/etc/caminos
  2. APPEND en que las listas de los caminos en el archivos en el directorio /etc/paths.d
  3. mutan la variable PATH para eliminar los elementos en la lista
  4. APPEND en la lista el valor de la variable de PATH mutado
  5. Guardar esta lista como el nuevo PATH

reformular esto en pseudocódigo, lo que está haciendo es:

  1. NEWPATH = Read (/ etc/caminos)
  2. NEWPATH = $ NEWPATH + añadir + Read (/etc/paths.d/ *)
  3. PATH = $ PATH -minus- $ NEWPATH
  4. NEWPATH = $ NEWPATH + añadir + $ PATH
  5. PATH = $ NEWPATH

Lo traicionero de esto es que, si está configurando manualmente su RUTA, es probable que sea para agregar componentes que anulen los componentes de la ruta del sistema. Si se llama a path_helper cuando no lo espera, deshará los cambios colocando los componentes de ruta de todo el sistema por delante de los componentes de ruta.

¿Cómo se llamaría inesperadamente al asistente de ruta? Por ejemplo, es llamado por/etc/zshenv, que se invoca cada vez que se inicia un shell zsh, ya sea una subshell o una instancia de zsh llamada desde otra aplicación como emacs o lo que sea.

Lo he escrito con más detalle como un OpenRadar bug report on path_helper.

+0

Aquí hay un intento de mejorarlo, si alguien tiene ganas de usarlo/revisarlo https://github.com/yb66/path_helper – iain

+0

En OS El Capitan, 'path_helper' se llama en'/etc/zprofile' en lugar de '/ etc/zshenv', que yo diría que es * peor *. Al menos '/ etc/zshenv' fue lo primero que se originó, por lo que podría anular el' PATH' para todas las shells (interactivas, no interactivas) en '~/.zshenv'. Pero dado que '/ etc/zprofile' se obtiene después de' ~/.zshenv', si desea la misma 'PATH' para las shells interactivas y no interactivas, se ve obligado a repetir las modificaciones realizadas en' ~/.zshenv' en '~/.zprofile'. – rampion

Cuestiones relacionadas