Як / usr / bin / env знає, яку програму використовувати?


62

Коли я використовую shebang #!/usr/bin/env pythonдля запуску сценарію, як система знає, який pythonвикористовувати? якщо я шукаю pythonбін-шлях у змінних оточення, я нічого не знайду.

env | grep -i python

6
о, я думаю, я зрозумів це - він просто шукає ваш $ PATH для 'python'
tMC

Я теж про це задумався. І чому / usr / bin / env? на відміну від / bin / env або env, якщо він просто отримує список шляхів від env?
Faheem Mitha

Просто "env" не буде працювати, оскільки він повинен бути повним шляхом. Програма 'env' зазвичай знаходиться в / user / bin / env. У деяких дистрибутивах його можна також знайти як / bin / env, але безпечніше переходити з / usr / bin / env.
ретопи

Відповіді:


54

Шебанг очікує, що повний шлях до інтерпретатора буде використаний, тому наступний синтаксис був би невірним:

#!python

Якщо встановити такий повний шлях, це може спрацювати:

#!/usr/local/bin/python

але було б не портативна , як пітон може бути встановлений /bin, /opt/python/binабо де -то інше місце.

Використання env

#!/usr/bin/env python

це метод, що дозволяє портативному способу вказати до ОС повний шлях, еквівалентний тому, де pythonвперше знаходиться в PATH.


56

Рядок shebang (від "різкого удару", тобто #!) обробляється ядром. Ядро не хоче знати про такі змінні середовища, як PATH. Отже, ім'я в рядку shebang має бути абсолютним шляхом до виконуваного файлу. Ви також можете вказати додатковий аргумент для передачі цього виконуваного файлу перед назвою скрипту (із системними обмеженнями я тут не заходжу). Наприклад, для сценарію Python можна вказати

#!/usr/bin/python

в першому рядку, і коли ви виконаєте сценарій, ядро ​​насправді виконає /usr/bin/python /path/to/script. Але це не зручно: потрібно вказати повний шлях команди. Що робити , якщо у вас є pythonв /usr/binна деяких машинах і /usr/local/binна інших? Або ви хочете встановити PATHдля /home/joe/opt/python-2.5/binтого, щоб використовувати конкретну версію Python? Оскільки ядро ​​не виконає PATHпошук для вас, ідея полягає в тому, щоб ядро ​​запустило команду, яка по черзі шукає потрібного інтерпретатора в PATH:

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

Це path-lookup-commandповинно взяти ім'я виконуваного файлу як аргумент, шукати його PATHі виконувати: ядро ​​запуститься /fixed/path/to/path-lookup-command python /path/to/script. Як це відбувається, envкоманда робить саме це. Його головне призначення - запустити команду з іншим середовищем, але оскільки вона шукає ім'я команди $PATH, вона ідеально підходить для нашої мети тут.

Хоча це офіційно не гарантовано, історичні системи Unix при умови , envв /usr/bin, і сучасні системи зберегли це місце саме через широкого використання #!/usr/bin/env. Отже, на практиці спосіб визначити, що сценарій повинен виконувати улюблений інтерпретатор Python користувача

#!/usr/bin/env python

2
який з них кращий між envі which? оскільки з цього моменту ви отримаєте найбільш придатний для виконання файл з мого середовища PATH.
Nikhil Mulley

8
@NikhilMulley whichзнаходить виконуваний файл і друкує його шлях. envзнаходить програму, задану першим аргументом, і виконує її, передаючи їй решта аргументів.
Кевін

3
так це envпо whichсуті є eval версія .
Nikhil Mulley

6

Правильно, так що запустіть:

env | grep PATH

Ваш $ PATH - це список каталогів. Unix буде проходити через цей список каталогів по порядку, поки не знайде "python".

Ви можете побачити, який каталог він знайде, за допомогою команди "який":

which python

Цікаво, що я бачу різницю в пітоні sys.pathміж активованими 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']) та ./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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.