it-swarm-ru.tech

Как / usr / bin / env знает, какую программу использовать?

Когда я использую Шебанг #!/usr/bin/env python чтобы запустить скрипт, как система узнает, какой python использовать? если я ищу путь python bin в переменных окружения, я ничего не нахожу.

env | grep -i python
65
tMC

Шебанг ожидает, что будет использован полный путь к интерпретатору, поэтому следующий синтаксис будет неправильным:

#!python

Установка полного пути, как это может работать:

#!/usr/local/bin/python

но будет непереносимым, так как python может быть установлен в /bin, /opt/python/bin или в другом месте.

Используя env

#!/usr/bin/env python

это метод, позволяющий переносимым способом указать ОС полный путь, эквивалентный тому, где python впервые находится в PATH.

55
jlliagre

Строка Shebang (от "острого взрыва", т.е. #!) обрабатывается ядром. Ядро не хочет знать о переменных среды, таких как PATH. Таким образом, имя в строке Shebang должно быть абсолютным путем к исполняемому файлу. Вы также можете указать дополнительный аргумент для передачи в этот исполняемый файл перед именем скрипта (с системно-зависимыми ограничениями я не буду здесь вдаваться). Например, для сценария Python вы можете указать

#!/usr/bin/python

в первой строке, и когда вы выполняете скрипт, ядро ​​фактически выполняет /usr/bin/python /path/to/script. Но это не удобно: вам нужно указать полный путь к команде. Что если у вас есть python in /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 in /usr/bin, и современные системы сохранили это местоположение именно благодаря широкому использованию #!/usr/bin/env. Таким образом, на практике способ указать, что скрипт должен выполняться любимым пользователем Python

#!/usr/bin/env python
61

Хорошо, так что беги:

env | grep PATH

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

Вы можете увидеть, какой каталог он находит с помощью команды which:

which python
7
Dan Rue