Этак с начала времён (юниксовых, т.е. 1.01.1970) в начале скрипта рекомендовалос
использовать shebang / hashbang - строку, указывающую на используемый интерпретатор, например:
#!/bin/bash
echo 'hello world'
#!/usr/bin/python
print 'hello world'
#!/usr/bin/python3
print('hello world')
Недавно наткнулся на рекомендацию использовать вместо этого такую форму:
#!/usr/bin/env bash
echo 'hello world'
#!/usr/bin/env python
print 'hello world'
#!/usr/bin/env python3
print('hello world')
Пожалуйста, объясните, как это работает и в чём преимущества такого подхода? Есл
есть ограничения и/или недостатки по сравнению с обычным способом - то и о них хотелось бы услышать.
Ответы
Ответ 1
Основная идея - улучшение переносимости. Не гарантируется, что на различных системах исполняемый файл будет лежать по пути, который указан в shebang.
Использование env позволяет снизить этот риск за счет запуска команды на основе данных из переменной среды PATH
Более того, если по каким-либо причинам вместо стандартного исполняемого файла пользовател
хочет использовать свой, то ему достаточно добавить путь к этому файлу в PATH без необходимости исправления скриптов:
~ $ cp /bin/bash /home/soon/python
~ $ export PATH=/home/soon:$PATH
~ $ env python
[soon@archlinux ~]$ exit
В примере выше я скопировал bash к себе в домашнюю директорию (переименовав при это
файл в python), добавил путь в PATH и запустил python с помощью env, которая усужливо запустила bash, т.к. нашла его раньше.
Еще одним примером является использование виртуальных окружений при разработке н
Python (virtualenv). Поскольку они также перебивают PATH, env позволяет использовать нужную версию исполняемого файла:
~ $ workon black-box-challenge-2016-py2
~ (venv:black-box-challenge-2016-py2) $ env python
Python 2.7.11 (default, Mar 31 2016, 06:18:34)
[GCC 5.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print sys.executable
/home/soon/.virtualenvs/black-box-challenge-2016-py2/bin/python
>>>
Ответ 2
краткое резюме из информации, приведённой в ответах к этому вопросу и к аналогичным вопросам:
Why is it better to use “#!/usr/bin/env NAME” instead of “#!/path/to/NAME” as my shebang?
Why is #!/usr/bin/env bash superior to #!/bin/bash?
преимущества:
будет запущена программа не из конкретно указанного файла, а из того, что встретитс
первым в списке каталогов, заданных переменной окружения PATH пользователя, запустившего скрипт.
полезно для случаев, когда по указанному пути в системе, на которой будет выполнятьс
скрипт, такого файла нет, или когда пользователь модифицирует эту переменную окружения для того, чтобы выполнялась какая-то особая программа (другая реализация, другая версия).
недостатки:
будет запущена программа не из конкретно указанного файла, а из того, что встретитс
первым в списке каталогов, заданных переменной окружения PATH пользователя, запустившего скрипт.
например, разные пользователи (или тот же пользователь, но с модифицированным содержимы
этой переменной окружения) могут получить разные результаты выполнения одного и того же скрипта.
программы /usr/bin/env может не существовать в системе, где будет запускаться скрипт, соответственно, попытка запуска будет неудачной.
нельзя будет указать дополнительной опции для выполняемой программы. так получится:
#!/путь/к/программе опция
а так — нет:
#!/usr/bin/env программа опция
Ответ 3
Это связано с переносимостью скриптов. Дело в том, что путь к python, к примеру
на разных системах может отличаться, а вот путь к env на всех системах неизменный. Поэтому
вызывая env и передавая ей в качестве аргумента нужный интерпретатор, можно быть уверенным, что скрипт будет запущен вне зависимости от того, где на самом деле находится интерпретатор (главное, чтобы он был в PATH).
Ответ 4
Команда env отображает текущие переменые окружения. А если стоит с командой
env bash
то выполняет команду с текущеми перемеными окружения.
В некоторых системах при запуске интерпритаторов используется не текущие перемены
окружения , а считываются из файлов или даже ставятся по умолчанию. И если Вы изменили или добавили переменые окружения , то они не будут учтены в запускаемом скрипте, а при запуске через env все переменые будут учтены.
Комментариев нет:
Отправить комментарий