Який тип шляху в шебангу є більш кращим?


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 .


Я щойно почав шукати Рубі, і я виявив, що умова в Рубі починається з [code] #! / Usr / bin / env ruby ​​[/ code] задля переносимості. Деякі зазначають, що це ускладнює надання аргументів командного рядка інтерпретатору рубіну, наприклад, "-w", що також буде проблемою для Perl.
bgvaughan

@bgvaughan Для Perl сьогодні традиційно просто використовувати, #!/usr/bin/perlа потім використовувати use strict; use warnings;в тілі сценарію, а не #!/usr/bin/perl -w. Але -Tмає бути на шебангу.
Кіт Томпсон

так чому б не використовувати #! perl, якщо ми просто хочемо першого на шляху?
звідки

@wheredidthatnamecomefrom: Тому що це не працює. Обробка #!лінії не застосовується $PATH. Ви повинні вказати шлях перекладача. (Я щойно зрозумів, що, принаймні, в моїй системі, це може бути відносний шлях, але це рідко корисно.)
Кіт Томпсон

6

Найкраща практика така:

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

І так далі...

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


Очевидним альтернативним виправленням проблеми тире було написання #!/bin/bash. Я погоджуюся, що автор сценарію несе відповідальність за уточнення перекладача, але все це означає, якщо вам потрібен удар, скажіть, баш не ш
Мартін Боннер підтримує Моніку

1

FYI, це ши-банг #!, вам потрібен #. Цей рядок ви використовуєте для визначення інтерпретатора для запуску сценарію.

За замовчуванням Ubuntu посилається /bin/shна тире

Залежно від того, скільки ви хочете знати про тире і чому тире використовується для системних або діамантових оболонок, див:

cyberciti.biz тире

Сторінка Man Ubuntu

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

Сценарій, написаний для perl, python тощо, взагалі не працюватиме з /bin/shабо /bin/bash.

Отже, коли ви пишете сценарій, ви визначаєте, який інтерпретатор повинен використовуватися з shee-bang

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


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.