Come fa / usr / bin / env a sapere quale programma usare?


62

Quando uso Shebang #!/usr/bin/env pythonper eseguire uno script, come fa il sistema a sapere quale pythonutilizzare? se cerco un pythonpercorso bin nelle variabili d'ambiente non trovo nulla.

env | grep -i python

6
oh, penso di averlo capito, cerca solo 'python' nel tuo $ PATH
tMC

Mi sono chiesto anche questo. E perché / usr / bin / env? al contrario di / bin / env o env, se sta semplicemente ottenendo un elenco di percorsi da env?
Faheem Mitha,

Solo 'env' non funzionerà perché deve essere un percorso completo. Il programma 'env' si trova di solito in / user / bin / env. In alcune distro può anche essere trovato come / bin / env, ma è più sicuro andare con / usr / bin / env.
Rettops

Risposte:


55

Shebang si aspetta che venga utilizzato un percorso completo per l'interprete, pertanto la sintassi seguente non sarebbe corretta:

#!python

L'impostazione di un percorso completo come questo potrebbe funzionare:

#!/usr/local/bin/python

ma sarebbe non portatile come pitone potrebbe essere installato in /bin, /opt/python/bin, o dovunque altro luogo.

utilizzando env

#!/usr/bin/env python

è un metodo che consente in modo portatile di specificare al sistema operativo un percorso completo equivalente a quello in cui pythonsi trova per la prima volta nel file PATH.


57

La linea shebang (da "sharp bang", cioè #!) viene elaborata dal kernel. Il kernel non vuole conoscere variabili di ambiente come PATH. Quindi il nome sulla riga shebang deve essere un percorso assoluto per un eseguibile. Puoi anche specificare un argomento aggiuntivo da passare a quell'eseguibile prima del nome dello script (con restrizioni dipendenti dal sistema che non entrerò qui). Ad esempio, per uno script Python, è possibile specificare

#!/usr/bin/python

sulla prima riga e quando si esegue lo script, il kernel verrà effettivamente eseguito /usr/bin/python /path/to/script. Ma non è conveniente: devi specificare il percorso completo del comando. Cosa fare se avete pythonin /usr/binsu alcune macchine e /usr/local/binsugli altri? O vuoi impostarlo PATHsu in /home/joe/opt/python-2.5/binmodo da utilizzare una versione specifica di Python? Dato che il kernel non farà la PATHricerca per te, l'idea è di far eseguire al kernel un comando che a sua volta cerca l'interprete desiderato nel PATH:

#!/fixed/path/to/path-lookup-command python

Questo path-lookup-commanddeve prendere il nome di un eseguibile come argomento e cercarlo PATHed eseguirlo: il kernel verrà eseguito /fixed/path/to/path-lookup-command python /path/to/script. Come succede, il envcomando fa proprio questo. Il suo scopo principale è quello di eseguire un comando con un ambiente diverso, ma poiché cerca il nome del comando $PATH, qui è perfetto per il nostro scopo.

Anche se questo non è ufficialmente garantita, i sistemi Unix storici forniti envin /usr/bin, e sistemi moderni hanno mantenuto quella posizione proprio per l'uso diffuso di #!/usr/bin/env. Quindi, in pratica, il modo per specificare che uno script deve essere eseguito dall'interprete Python preferito dall'utente è

#!/usr/bin/env python

2
quale è preferito tra enve which? da cui otterrò anche l'eseguibile più idoneo dal mio ambiente PATH.
Nikhil Mulley,

8
@NikhilMulley whichtrova l'eseguibile e stampa il suo percorso. envtrova il programma specificato dal primo argomento e lo esegue, passando gli argomenti rimanenti.
Kevin,

3
così è essenzialmente envuna versione negativa di whichessenzialmente.
Nikhil Mulley,

7

Bene, quindi corri:

env | grep PATH

$ PATH è un elenco di directory. Unix passerà attraverso quell'elenco di directory, in ordine, fino a quando non troverà "Python".

Puoi vedere quale directory trova con il comando 'which':

which python

È interessante notare che sto vedendo una differenza nel pitone sys.pathtra un attivato env $ env python3 ( ['', '/home/user/test', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/home/user/.local/lib/python3.4/site-packages', '/usr/lib/python3.4/site-packages', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']) e ./env/bin/python3 (['', '/home/user/test', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/home/user/test/env3/lib/python3.4/site-packages']).
ThorSummoner,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.