Jaki rodzaj ścieżki w shebang jest bardziej preferowany?

20

W skryptach pierwsza linia powinna określać ścieżkę do interpretera.
Ale na różnych serwerach Linux, Unix lub BSD ta ścieżka może być inna.

Co jest bardziej korzystne?

#!/usr/bin/env bash 

lub

#!/bin/bash 
Roman Iwanow
źródło

Odpowiedzi:

22

Jeśli chcesz użyć zainstalowanej przez system wersji danego interpretera, który jest zainstalowany w standardowej lokalizacji, użyj ścieżki bezpośredniej. Jeśli chcesz użyć dowolnej wersji interpretera, która pojawi się jako pierwsza u użytkownika $PATH, użyj #!/usr/bin/env ....

envKomenda wywołuje określoną komendę, pozwalając Włącza lub wyłącza zmienne środowiskowe:

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

Jeśli nie określisz żadnych zmiennych środowiskowych ani innych opcji, po prostu wywoła nazwane polecenie. (Korzystanie z tego w ten sposób jest prawdopodobnie trochę włamaniem).

Celem napisania shebang jako

#!/usr/bin/env interp

jest wywoływanie tego, co interppojawi się jako pierwsze w $PATH.

Oznacza to, że nie trzeba znać, pisząc scenariusz, dokładnie tam, gdzie interpjest (powiedzmy, jeśli mogłoby to być albo /bin, /usr/binalbo /usr/local/bin). Oczywiście, że trzeba wiedzieć, że envjest /usr/bin/env, ale to wydaje się być dość powszechne.

Zaletą jest to, że wywołuje dowolną wersję interpretera, która pojawi się jako pierwsza u użytkownika $PATH. Wadą jest to, że wywołuje w zależności od wersji interpretera pierwszy pojawia się w instrukcji $PATH.

Załóżmy na przykład, że zainstalowałem osobistą kompilację perlw moim katalogu domowym, ponieważ $HOME/bin/perlmam to $HOME/binz przodu $PATH. Jeśli uruchomię skrypt, którego shebang jest

#!/usr/bin/env perl

to będzie działać z moim własnym perlplikiem wykonywalnym - co może nie być dobrą rzeczą. Autor skryptu prawdopodobnie nie przetestował go z najnowocześniejszym Perlem, który zbudowałem ze źródła miesiąc temu.

Dla czegoś takiego jak Perl lub Bash, który prawdopodobnie zostanie zainstalowany w spójnej lokalizacji na większości systemów ( /usr/bin/perli /bin/bashodpowiednio), użyłbym bezpośredniej ścieżki do polecenia. Aby uzyskać coś bardziej niejasnego, który mógłby zostać zainstalowany inaczej w różnych systemach, skorzystałbym ze /usr/bin/envsztuczki lub napisałbym instalator, który dostosowuje linię shebang podczas instalowania skryptu. (Kiedyś musiałem to robić dla moich skryptów Perla.)

AKTUALIZACJA: Zagłębiłem się bardziej szczegółowo w tej odpowiedzi na to pytanie na stronie Unix i Linux .

Keith Thompson
źródło
Właśnie zacząłem patrzeć na Ruby i odkryłem, że konwencja w Ruby zaczyna się od [code] #! / Usr / bin / env ruby ​​[/ code] ze względu na przenośność. Niektórzy zauważyli, że utrudnia to dostarczanie argumentów wiersza poleceń do interpretera ruby, takich jak „-w”, co również stanowiłoby problem dla Perla.
bgvaughan
@bgvaughan W przypadku Perla tradycyjne jest obecnie używanie, #!/usr/bin/perla następnie używanie use strict; use warnings;w treści skryptu, a nie #!/usr/bin/perl -w. Ale -Tmusi być w zgiełku.
Keith Thompson,
więc dlaczego nie użyć #! perl, jeśli chcemy tylko pierwszego na ścieżce?
wheredidthatnamecom od
@wheredidthatnamecomefrom: Ponieważ to nie działa. Leczenie #!linii nie działa $PATH. Musisz podać ścieżkę tłumacza. (Właśnie zdałem sobie sprawę, że przynajmniej w moim systemie może to być ścieżka względna, ale to rzadko przydatne).
Keith Thompson
6

Najlepsza praktyka jest następująca:

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

I tak dalej...

Kiedy Ubuntu po raz pierwszy zaczął używać dash, niektóre skrypty uległy awarii. Dyskutowano o tym. Napisano większość skryptów, #!/bin/shktóre były linkiem do / bin / bash. Konsensus jest następujący: autor skryptów jest odpowiedzialny za określenie tłumacza. Dlatego jeśli twój skrypt powinien być zawsze wywoływany za pomocą BASH, określ go ze środowiska. Dzięki temu nie musisz zgadywać ścieżki, która jest różna w różnych systemach Unix / Linux. Ponadto zadziała, jeśli jutro / bin / sh stanie się linkiem do innej powłoki, takiej jak / bin / wthsh lub innej nieobecności.


źródło
Oczywistą alternatywną poprawką dla problemu deski rozdzielczej było pisanie #!/bin/bash. Zgadzam się, że autor skryptów jest odpowiedzialny za określenie interpretera, ale to wszystko oznacza, że jeśli potrzebujesz bash, powiedz bash nie sh
Martin Bonner obsługuje Monikę
1

FYI to shee-bang #!, potrzebujesz #. Za pomocą tego wiersza można określić, z jakim tłumaczem ma zostać uruchomiony skrypt.

Domyślnie Ubuntu prowadzi /bin/shdo myślnika

W zależności od tego, ile chcesz wiedzieć o kresce i dlaczego kreska jest używana dla powłok systemowych lub deamon, zobacz:

cyberciti.biz dash

Strona podręcznika użytkownika Ubuntu

Bash jest domyślną powłoką używaną przez większość użytkowników Linuksa i ma inne funkcje niż dash. Skrypt napisany dla basha może, ale nie musi, działać poprawnie, jeśli jest uruchamiany z myślnikiem, im bardziej złożony skrypt, tym mniejsze prawdopodobieństwo, że zostanie uruchomiony.

Skrypt napisany dla Perla, Pythona itp. W ogóle nie będzie działał z /bin/shlub /bin/bash.

Kiedy piszesz skrypt, określasz, jakiego interpretera należy używać z shee-bang

Wyboru tego, czego użyć, dokonuje autor skryptu, a jeden nie jest lepszy od drugiego, wszystkie mają różne funkcje, zalety i wady.

Pantera
źródło