2012-09-13 19 views
10

Ho installato rbenv tramite homebrew e ora non so perché path_helper metta ~/.rbenv/shims alla fine del percorso invece che all'inizio. E, cosa più importante, in che modo path_helper ha ottenuto queste informazioni?OS X Mountain Lion: come funziona path_helper?

In base alla pagina man di path_helper, legge le voci da/etc/paths e dai file in /etc/paths.d. Ma non riesco a trovare la stringa ".rbenv/shims" lì.

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

risposta

6

Ho il sospetto che il vostro .bash_profile o .bashrc è l'aggiunta di .rbenv/shims al PATH, e che è in esecuzione ad un certo punto, prima path_helper viene richiamato durante il guscio di start-up.

La pagina man per path_helper si apre 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. 

Il punto cruciale è che l'utilità path_helper ha lo scopo di aggiungere contenuti a un PATH impostazione esistente, non sostituirli. (E in realtà, ciò che realmente fa è prepend contenuti, non li aggiungere, che conta per PATH variabili ...)

Quindi, se mi metto fuori con una voce sul mio PATH, ha generato l'impostazione by path_helper farà in modo che la voce continui sul PATH che 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; 

Nota che foo è stato incluso nel mio percorso nell'ultima riga, anche se il contenuto di /etc/paths e /etc/paths.d/* non sono cambiate.

Allo stesso tempo, anche l'utilità path_helper sembra fare attenzione a non produrre percorsi con voci duplicate; rimuove le voci duplicate dopo aver concatenato /etc/paths e /etc/paths.d/* e l'attuale PATH.

Quest'ultimo dettaglio può essere particolarmente confuso poiché può causare il riordino delle voci rispetto all'impostazione originale PATH (!).

Di seguito sono riportati alcuni esempi di questo comportamento: Il primo caso mostra un duplicato foo rimosso. Il secondo e il terzo caso illustrano il riordino della voce: il PATH generato è lo stesso in entrambi i casi, ma nel terzo caso la voce /usr/bin è stata spostata da foo e bar nella parte anteriore dello PATH. (Questa rimozione di voci duplicate sembra essere basata sulla semplice corrispondenza di stringhe sulle coppie di voci, come illustrato dal quarto caso in basso in cui la stringa /usr/bin/ rimane compresa tra foo/ e 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; 

Infine, per dare credito quando il credito è dovuto: Mentre tutti le sequenze di comando di cui sopra sono il risultato delle mie ricerche, mi è stato originariamente ispirato a esaminare il comportamento di path_helper dopo aver letto la nota here , che ha evidenziato che path_helper riutilizza la variabile di ambiente PATH impostata dal processo padre.

+1

Grazie per aver sottolineato che, contrariamente ai documenti, path_helper * antepone * i percorsi e rimuove i duplicati. – algal

6

La pagina man path_helper non è corretta. La pagina man dice che path_helper aggiunge /etc/paths.d al PATH. In realtà, path_helper è APPENDERE /etc/paths.d nella lista da/etc/paths e quindi PREPENDERE efficacemente quel risultato su PATH preesistente (oltre a cancellare il PATH dei duplicati sovrascritti da quella lista).

Per essere precisi, si parla solo di PATH per esempio, ciò che fa è:

  1. leggere l'elenco dei percorsi nel file/etc/percorsi
  2. APPEND su di esso gli elenchi dei percorsi nel i file nella directory /etc/paths.d
  3. mutano la variabile PATH per rimuovere tutti gli elementi nella lista
  4. APPEND sulla lista il valore del percorso mutato variabile
  5. Salva questa lista come il nuovo percorso

riformulare questo pseudocodice, quello che sta facendo è:

  1. Newpath = Leggi (/ etc/percorsi)
  2. Newpath = $ Newpath + aggiungere + Read (/etc/paths.d/ *)
  3. PATH = $ PATH -minus- $ newpath
  4. newpath = $ newpath + aggiungere + $ PATH
  5. PATH = $ newpath

Ciò che è insidioso è che, se si sta configurando manualmente il PERCORSO, è probabilmente necessario aggiungere componenti che sostituiscono i componenti del percorso di sistema. Se path_helper viene chiamato quando non se lo aspetta, annulla le modifiche mettendo i componenti del percorso a livello di sistema in anticipo rispetto ai componenti del percorso.

Come viene chiamato inaspettatamente l'helper del percorso? Ad esempio, viene chiamato da/etc/zshenv, che viene chiamato ogni volta che si avvia una shell zsh, che si tratti di una subshell o di un'istanza zsh chiamata da un'altra app come emacs o altro.

L'ho scritto più dettagliatamente come OpenRadar bug report on path_helper.

+0

Ecco un tentativo di migliorarlo, se qualcuno ha voglia di usarlo/controllarlo su https://github.com/yb66/path_helper – iain

+0

In OS El Capitan, 'path_helper' è chiamato in'/etc/zprofile' piuttosto che '/ etc/zshenv', che direi che è * peggio *. Almeno '/ etc/zshenv' è stata la prima cosa creata, quindi è possibile sovrascrivere il' PATH' per tutte le shell (interattive, non interattive) in '~/.zshenv'. Ma dal momento che '/ etc/zprofile' è originato dopo' ~/.zshenv', se vuoi lo stesso 'PATH' per le shell interattive e non interattive sei costretto a ripetere le modifiche fatte in' ~/.zshenv' in '~/.zprofile'. – rampion

Problemi correlati