У чому сенс і переваги #!/usr/bin/env?
З початку часів (юніксових, тобто 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
>>>