No. 196

Titolo originale: The $PATH to Enlightenment

Pubblicato in:

Scritto da Olivier Lacan

Il software open source richiede sempre un po' di setup noioso. Sebbene possa sembrare che distragga dallo scopo finale (ossia risolvere problemi usando quei tool), in realtà il processo di setup è spesso un'opportunità per famigliarizzare con uno degli strumenti più importanti del mestiere: la riga di comando.

La riga di comando fa di per sé paura a molte persone: è una tecnologia arcana che nella cultura popolare viene associata agli “hacker” e ai “maghi del computer”. In realtà, però, non è così cool: è un insieme di strumenti estremamente semplici creati dagli impiegati della Bell (ora AT&T) per compiere dei semplici task negli anni '70. Fa parte di quella tecnologia “spaziale” in cui rientra anche il microonde.

È anche estremamente utile, come passare dal fare una casa a mano all'utilizzare degli utensili elettrici. E attraverso qualche concetto e alcune metafore possiamo far luce su uno degli angoli più scuri di questa riga di comando.

Uno dei concetti più importanti è il Path.

Molti framework front-end, CSS preprocessor, librerie JavaScript e altri tool di sviluppo web dipendono dall'installazione di Ruby o Node.js sulla vostra macchina. Bower è uno di questi tool. Invariabilmente, questi strumenti vi porteranno ad interagire con Path. Questo accade perché Path dovrà essere cosciente di tutti i tool che installate per il vostro ambiente di sviluppo perché la riga di comando funzioni a dovere.

Comprendere il funzionamento di Path potrebbe sembrare un passo indietro, ma più si usano i tool da riga di comanda, maggiori sono le possibilità che Path vi causerà dei problemi. Prima che perdiate ore - o che cominciate a tirare oggetti allo schermo - vediamo insieme le basi dell'uso di Path.

Un'umile, piccola variabile

$PATH, come denotato dal prefisso dollaro e dal maiuscolo che sembra un grido, è una variabile d'ambiente Unix. In questa variabile viene memorizzata una lista, delimitata da due punti, di percorsi di directory. Qualcosa tipo:

/root/directory/binary:/root/other_directory/other_binary

Se siete degli “aficionados” dei nomi delle variabili, potreste chiedervi perché non è stata chiamata $PATHS, dal momento che contiene più percorsi. Se dovessi tirare a indovinare, direi che il nome singolare probabilmente fa riferimento “al percorso di caricamento composto da più path individuali&rquo;. Facciamocelo andare bene così.

Ora, se siete curiosi riguardo a quali altri tipi di variabili di ambiente esistono nel vostro sistema, potete scrivere il comando env nel vostro prompt della riga di comando. Premete Enter e vedrete un elenco di tutte le variabili ambiente che esistono al momento.

Poiché $PATH è una variabile, può essere modificata a vostro piacimento, al volo. Per esempio, potete far girare questo nella shell:

$ export PATH=banana

Cosa fa? Beh, cerca di far girare il comando export in una nuova finestra all'interno del vostro terminale o in qualsiasi shell app usiate, come Terminal su OS X.

Poi, scrivete un qualunque comando Unix di base tipo ls (elenca il contenuto della directory). Vedrete -bash: ls: command not found quando ls invece ha sempre funzionato tranquillamente.

Questo subdolo sabotaggio è utile perché adesso sappiamo che senza il contenuto all'interno del nostro $PATH, tutto impazzisce.

Ma perché? Perché come molti load path fanno (includendo nei linguaggi di programmazione e nei web framework come Rails), questo Path determina cosa può essere eseguito nella vostra shell. Se la vostra shell non riesce a trovare nulla che si abbini al nome che avete inserito, non può far girare quel comando.

Oh, tra l'altro, uscite e riavviate la vostra applicazione shell per ripristinare tutti i comandi. Questo è stato un sabotaggio temporaneo. State però attenti a non salvarlo mai nel vostro ~/.bash_profile. Lì sì che farebbe danni.

Una storia di moltissimi binaries

In Unix, alcuni eseguibili vengono chiamati binaries. Si tratta, in tutta onestà, di un nome piuttosto brutto, dal momento che si concentra sul loro formato piuttosto che sulla loro funzione. Quando scrivete un programma Unix per svolgere un task, a volte dovete compilarne il codice sorgente prima che possa essere eseguito. Questo processo di compilazione crea il binary. Invece di usare del semplice testo (come il codice sorgente), questi files usano dei formati binari per semplificare al computer il processing delle istruzioni.

Ci sono più directory in Unix in cui memorizzare i binaries. Potete vedere quale sia la directory di default usata per caricare i binaries nel file /etc/paths.

# the cat command can print the content of a file
$ cat /etc/paths 
/usr/bin 
/bin 
/usr/sbin 
/sbin 
/usr/local/bin

Il file contiene una directory per riga. I path sono elencati in un ordine significativo. Quando viene trovato un binary in un path, viene caricato. Se viene trovato un binary con lo stesso nome in un altro path, viene ignorato. Pertanto, i path elencati prima hanno la precedenza sui path elencati dopo.

Questo è il motivo per cui è facile avere problemi quando si cerca di installare un binary per qualcosa che esiste già nel vostro sistema. Nel caso di OS X, se cercate di installare una versione diversa di Git rispetto a quella che è installata nel sistema, vi imbatterete in questo problema. Il che è un peccato, perché Git 2.0 è molto carino.

Se faccio cd (cambia directory) in /usr/bin, una directory comune in cui vengono memorizzati i binaries, e dò il comando ls, ricevo più di 1000 risultati. Ciò non mi è di molto aiuto. Detto questo, se al contrario uso [grep](http://en.wikipedia.org/wiki/Grep) con ls | grep git, posso filtrare solo i risultati del comando ls che contengono git.

$ ls | grep git 
git
git-cvsserver
git-receive-pack
git-shell 
git-upload-archive 
git-upload-pack

Era piuttosto ovvio che ci fosse un binary per Git all'interno di /usr/bin. Una nuova installazione di OS X dovrebbe dare /usr/bin/git quando si dà il comando which git:

$ which git 
/usr/local/bin/git

Allora perché il mio è diverso? Possiamo avere un'idea migliore di quello che sta succedendo usando l'opzione -a quando usiamo which:

$ which -a git
/usr/bin/git
/usr/local/bin/git

Questo mi dice che ci sono due versioni di Git installate sul mio sistema. Solo la prima è usata quando eseguo i comandigit dalla mia riga di comando.

Cambiare i path

Utilizzando un package manager per OS X chiamato Homebrew, ho installato la mia versione di Git perché mi piace avere il controllo dei tool che uso ogni giorno e aggiornarli quando ne sento il bisogno. Potrei aggiornare la versione di sistema installata da OS X, ma non ho idea di quali altri binaries o app dipendano da essa.

Abbiamo visto che si cercano i binary files in base all'ordine in cui sono memorizzati in un file chiamato /etc/paths, ma allora perché non cambiamo quell'ordine?

All'interno del file /etc/paths vedo che la cartella /usr/local/bin nella quale si trova la mia versione di Git installata con Homebrew è in ultima posizione. Ciò significa che il binary di git all'interno di /usr/bin avrà la precedenza su di esso e la mia bellissima versione di Git sarà ignorata. E non va bene.

Ora, potreste provare a modificare l'ordine in /etc/paths in modo che soddisfi i vostri bisogni mettendolo in /usr/local/bin proprio in cima. La versione di Git installata da Homebrew a quel punto si caricherebbe per prima, ma, indipendentemente da quante volte vedrete questo suggerimento ripetuto nelle discussioni su Stack Overflow, non fatelo. Mai. Le configurazioni memorizzate in /etc/ influenzano l'intero sistema. Non sono lì per essere cambiate dai singoli utenti (sì, anche se voi siete gli unici ad usare la vostra macchina), e potreste benissimo causare dei danni imprevisti trafficando là dentro. Per esempio, alcune utility usate da OS X potrebbero far affidamento sull'ordine originale di /etc/paths.

Al contrario, dovreste modificare il $PATH nel vostro ambiente, usando il vostro .bash_profile, quello memorizzato in /Users/yourusername/.bash_profile.

Tutto quello che dovete fare per essere sicuri che </usr/local/bin venga considerato per primo è includere il seguente comando nel vostro .bash_profile:

# inside /Users/olivierlacan/.bash_profile
export PATH=/usr/local/bin:$PATH

Questo esporta una nuova variabile di ambiente $PATH stampando quella esistente e semplicemente appendendo prima il percorso /usr/local/bin sulla sinistra di tutti gli altri percorsi. Dopo aver salvato il vostro ~/.bash_profile e aver riavviato la vostra shell, questo è quello che dovreste vedere quando chiamate echo sul $PATH:

$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin

Come potete vedere, /usr/local/bin è menzionato due volte nel $PATH ed è corretto. Dal momento che è menzionato per primo, tutti i binaries che saranno caricati per la prima volta saranno ignorati quando sarà visitato per ultimo. Onestemente, io vorrei che ci fosse un modo più sicuro e semplice per cambiare l'ordine dei percorsi, ma la maggior parte delle soluzioni di cui sono a conoscenza sono un po' troppo complesse. Potreste sempre sovrascrivere direttamente il $PATH di default, ma presume che sappiate esattamente quello che state facendo e che percorsi includere.

Una "bi-fork-azione" nel percorso

Ora che avete cambiato a vostro piacimento il $PATH, potete controllare che il binary appropriato venga chiamato quando usate il comando git:

$ which git 
/usr/local/bin/git 

$ git --version 
git version 2.0.0
/usr/bin/git --version git version 1.8.5.2 (Apple Git-48)

Ecco fatto. Git 2.0.0 (la versione installata da Homebrew) è ora quella che risponde ai comandi git e la versione 1.8.5.2 installata da Apple passa in background. Se invece preferite non usare Git 2.0.0, potete semplicemente disinstallarla e la versione di default la sostituirà in maniera impercettibile.

Proteggete il vostro path

Un insieme di utility per developer (e designer) farà automaticamente inject di codice nel vostro .bash_profile dopo l'installazione. Spesso non ve lo diranno nemmeno, quindi se trovate degli strani percorsi elencati nel vostro profilo, questo potrebbe spiegare perché caricare una nuova sessione (cosa che accade quando aprite una nuova finestra o tab della shell) prende più tempo di quel che dovrebbe: un $PATH troppo pieno potrebbe a volte prendere un po' di tempo per caricarsi.

Ecco il mio path oggi:

/Users/olivierlacan/.rbenv/shims:/Users/olivierlacan/.rbenv/bin:
  /usr/local/bin:/usr/local/heroku/bin:/usr/bin:/bin:/usr/sbin:/sbin:
  /usr/local/bin:/opt/X11/bin:/usr/local/MacGPG2/bin

È un po' difficile da leggere, quindi tendo a spezzarlo su più righe. Potete farlo facilmente con il comando tr (translate characters):

$ echo $PATH | tr ':' '\n'
/Users/olivierlacan/.rbenv/shims
/Users/olivierlacan/.rbenv/bin
/usr/local/bin
/usr/local/heroku/bin
/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/bin
/opt/X11/bin
/usr/local/MacGPG2/bin

Ci sono molte cose in corso qui, ma è molto più facile capirle con un po' di verticalità. Provate e se non sapete perché una di queste righe si trova nel vostro $PATH, abbiate come obiettivo quello di capirlo. Potreste semplicemente imparare qualcosa di utile.

Essere più coscienti del proprio $PATH e del modo in cui funziona potrebbe non sembrare il pezzo più tangibile di conoscenza. Tuttavia, come lavoratore del web, probabilmente dovrete interagire con dei tool da riga di comando mentre lavorate e, un giorno, qualcosa potrebbe andar storto con uno di questi tool. Adesso che sapete cosa sia il vostro Path, come appare quando è pulito, come modificarlo appropriatamente e come controllare che sia cosciente dei vostri tool, c'è una buona chance che passiate dei minuti invece di ore a tornare sul vostro percorso: quello in cui create cose per le persone.

Illustrazioni: Carlo Brigatti

Share/Save/Bookmark
 

Discutiamone

Ti sembra interessante? Scrivi tu il primo commento


Cenni sull'autore

Olivier Lacan

Olivier Lacan è un software developer di Code School. Fare solo metà del lavoro come web designer non lo soddisfava, perciò è diventato dipendente dalla programmazione in Ruby. Ora scrive di vari argomenti e cerca di rendere il mondo del software open source più accogliente.

Questo sito per poter funzionare utilizza i cookie. Per saperne di più visita la pagina relativa all' INFORMATIVA