Какой тип пути в Шебанге является более предпочтительным?

20

В скриптах первая строка должна указывать путь к интерпретатору.
Но на разных серверах Linux, Unix или BSD этот путь может быть разным.

Что предпочтительнее?

#!/usr/bin/env bash 

или

#!/bin/bash 
Роман Иванов
источник

Ответы:

22

Если вы хотите использовать установленную системой версию данного интерпретатора, установленного в стандартном месте, используйте прямой путь. Если вы хотите использовать любую версию интерпретатора, которая появляется первой у пользователя $PATH, используйте #!/usr/bin/env ....

Команда envвызывает указанную команду, позволяя вам устанавливать или сбрасывать переменные окружения:

env FOO=BAR do-something
env DISPLAY=:0.0 xterm -ls &

Если вы не укажете какие-либо переменные окружения или другие параметры, он просто вызовет именованную команду. (Использовать его таким образом, возможно, немного хак.)

Цель написания Шебанга как

#!/usr/bin/env interp

это вызвать все, что interpпоявляется первым в $PATH.

Это означает , что вы не должны знать, когда писал сценарий, где именно interpнаходится (скажем, если он может быть в любом /bin, /usr/binили /usr/local/bin). Конечно, вы должны знать, что envэто так /usr/bin/env, но это кажется достаточно универсальным.

Преимущество состоит в том, что он вызывает любую версию интерпретатора, которая появляется первой у пользователя $PATH. Недостаток является то , что он вызывает какая версия интерпретатора появляется первой в пользователе $PATH.

Например, предположим, что я установил личную сборку в perlсвоем домашнем каталоге, как $HOME/bin/perlи у меня $HOME/binв передней части $PATH. Если я запускаю скрипт, чей шебанг

#!/usr/bin/env perl

тогда он будет запущен с моим собственным установленным perlисполняемым файлом - что может быть не очень хорошо. Автор сценария, вероятно, не проверял его с использованием Perl, который я создал из исходного кода месяц назад.

Для чего-то вроде Perl или Bash, которые могут быть установлены в согласованном месте на большинстве систем ( /usr/bin/perlи /bin/bash, соответственно), я бы использовал прямой путь к команде. Для чего-то более неясного, что могло бы быть установлено по-разному в разных системах, я бы либо воспользовался /usr/bin/envуловкой, либо я бы написал установщик, который корректирует строку shebang по мере установки скрипта. (Раньше я делал это для моих скриптов Perl.)

ОБНОВЛЕНИЕ: В этом ответе на этот вопрос я подробно остановился на сайте Unix & Linux .

Кейт Томпсон
источник
Я только начал изучать Ruby и обнаружил, что в Ruby принято начинать с [code] #! / Usr / bin / env ruby ​​[/ code] для удобства переносимости. Некоторые отметили, что это затрудняет предоставление аргументов командной строки для интерпретатора ruby, такого как '-w', что также будет проблемой для Perl.
bgvaughan
@bgvaughan Для Perl в наше время традиционно просто использовать, #!/usr/bin/perlа затем использовать use strict; use warnings;в теле сценария, а не #!/usr/bin/perl -w. Но -Tдолжен быть на Шебанге.
Кит Томпсон
так почему бы не использовать #! perl, если мы просто хотим получить первый путь?
имени
@weredidthatnamecomefrom: потому что это не работает. Лечение #!линии не использовать $PATH. Вы должны указать путь переводчика. (Я только что понял, что, по крайней мере, в моей системе, это может быть относительный путь, но это редко полезно.)
Кит Томпсон
6

Лучшая практика заключается в следующем:

#!/usr/bin/env bash 
#!/usr/bin/env sh
#!/usr/bin/env python

И так далее...

Когда Ubuntu впервые начал использовать dash, некоторые скрипты сломались. Была дискуссия по этому поводу. Большинство сценариев были написаны #!/bin/shс ссылкой на / bin / bash. Согласие таково: автор сценария отвечает за указание интерпретатора. Поэтому, если ваш скрипт всегда должен вызываться с помощью BASH, укажите его из среды. Это избавляет вас от необходимости угадывать путь, который отличается в разных системах Unix / Linux. Кроме того, это будет работать, если завтра / bin / sh станет ссылкой на какую-то другую оболочку, например / bin / wthsh, или на какую-то другую неявку.


источник
Очевидным альтернативным решением проблемы с тире было написать #!/bin/bash. Я согласен, что автор сценария отвечает за указание переводчика, но все, что это означает, это если вам нужен bash, скажем, bash, а не sh
Мартин Боннер поддерживает Monica
1

К вашему сведению, она #!нужна вам #. Вы используете эту строку, чтобы определить, с каким интерпретатором запускать скрипт.

По умолчанию Ubuntu ссылается /bin/shна dash

В зависимости от того, как много вы хотели бы узнать о dash и почему dash используется для системных оболочек или оболочек deamon, смотрите:

cyberciti.biz тире

Справочная страница Ubuntu dash

Bash является оболочкой по умолчанию, используемой большинством пользователей Linux, и имеет функции, отличные от dash. Сценарий, написанный для bash, может работать или не работать должным образом, если он запускается с помощью dash, чем сложнее скрипт, тем меньше вероятность его запуска.

Скрипт, написанный для perl, python и т. Д., Вообще не будет работать с /bin/shили /bin/bash.

Поэтому, когда вы пишете сценарий, вы определяете, какой интерпретатор следует использовать с ши-бен

Выбор того, что использовать, сделан автором сценария, и одно не лучше другого, все они имеют различные особенности, преимущества и недостатки.

пантера
источник