Dlaczego jest #!/usr/bin / ENV bash superior to #!/align = "left"/

Widziałem w wielu miejscach, w tym zalecenia na tej stronie (jaki jest preferowany shebang Bash?), aby użyć #!/usr/bin/env bash zamiast #!/bin/bash. Widziałem nawet jedną przedsiębiorczą osobę sugerującą, że używanie #!/bin/bash było złe a funkcjonalność bash zostałaby utracona w ten sposób.

Mówiąc wszystko, używam Basha w ściśle kontrolowanym środowisku testowym, gdzie każdy dysk w obiegu jest zasadniczo klonem pojedynczego dysku głównego. Rozumiem argument o przenośności, choć niekoniecznie ma to zastosowanie w moim przypadku. Czy jest jakiś inny powód, aby preferować #!/usr/bin/env bashnad alternatywami i, zakładając, że przenośność była problemem, czy jest jakiś powód, dla którego używanie go mogłoby złamać funkcjonalność?

 117
Author: Community, 2014-02-07

4 answers

#!/usr/bin/env wyszukuje PATH dla bash, a bash nie zawsze jest w /bin, szczególnie na systemach Nie-Linuksowych. Na przykład w moim systemie OpenBSD znajduje się w /usr/local/bin, ponieważ został zainstalowany jako opcjonalny pakiet.

Jeśli jesteś absolutnie pewien bash jest w /bin i zawsze będzie, nie ma nic złego w umieszczaniu go bezpośrednio w Twoim shebangu-ale polecam przeciwko temu, ponieważ skrypty i programy mają życie poza tym, co początkowo sądzimy, że będą miały.

 127
Author: zigg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-06 20:12:26

Standardowa lokalizacja bash to /bin i podejrzewam, że to prawda we wszystkich systemach. Co jednak, jeśli nie podoba Ci się ta wersja Basha? Na przykład Chcę użyć bash 4.2, ale bash na moim Macu jest w 3.2.5.

Mógłbym spróbować ponownie zainstalować Basha w /bin, ale to może być zły pomysł. Jeśli zaktualizuję system operacyjny, zostanie on nadpisany.

W przeciwieństwie do bash 'a, bash' a nie można używać w tym celu.]}
PATH="/usr/local/bin:/bin:/usr/bin:$HOME/bin"

Teraz, jeśli sprecyzuję bash, nie dostaję starego chrupiącego w /bin/bash, ale nowszy, lśniący na /usr/local/bin. Nieźle!

Tylko, że moje skrypty powłoki mają to !# /bin/bash shebang. Tak więc, kiedy uruchamiam moje skrypty powłoki, dostaję starą i kiepską wersję Basha, która nawet nie ma tablic asocjacyjnych.

Użycie /usr/bin/env bash użyje wersji Basha znalezionej w mojej ścieżce. Jeśli skonfiguruję ścieżkę tak, aby /usr/local/bin/bash była wykonywana, to jest to bash, którego będą używać moje Skrypty.

Rzadko można to zobaczyć z bashem, ale jest to o wiele bardziej powszechne w przypadku Perla i Python:

  • niektóre Wydania Uniksa / Linuksa, które koncentrują się na stabilności, są czasami znacznie opóźnione z wydaniem tych dwóch języków skryptowych. Nie tak dawno, PERL RHELA był w wersji 5.8.8-ośmioletnia wersja Perla! Jeśli ktoś chciał korzystać z bardziej nowoczesnych funkcji, musiał zainstalować własną wersję.
  • programy takie jak Perlbrew i Pythonbrew pozwalają zainstalować wiele wersji tych języków. Zależą od skryptów, które manipulują Twoją ścieżką, aby uzyskać wersja, którą chcesz. Twarde kodowanie ścieżki oznacza, że nie mogę uruchomić skryptu pod brew .
  • nie tak dawno temu (ok, dawno temu) Perl i Python nie były standardowymi pakietami zawartymi w większości systemów uniksowych. Oznacza to, że nie wiesz, gdzie zainstalowano te dwa programy. To było pod /bin? /usr/bin? /opt/bin? Kto wie? Używanie #! /usr/bin/env perl oznaczało, że nie musiałem wiedzieć.

A teraz dlaczego nie powinieneś używać #! /usr/bin/env bash

Gdy ścieżka jest zakodowana na twardo w muszę iść z tłumaczem. Dlatego #! /bin/bash zmusza mnie do używania domyślnej zainstalowanej wersji Basha. Ponieważ funkcje bash są bardzo stabilne (spróbuj uruchomić 2.x wersja skryptu Pythona pod Python 3.x) jest bardzo mało prawdopodobne, że mój skrypt BASH nie będzie działać, a ponieważ mój skrypt bash jest prawdopodobnie używany przez ten system i inne systemy, używanie niestandardowej wersji bash może mieć niepożądane efekty. Jest bardzo prawdopodobne, że chcę się upewnić, że stabilna wersja standardowa bash jest używany z moim skryptem powłoki. Tak więc, prawdopodobnie chcę ciężko kodować ścieżkę w moim shebang.

 24
Author: David W.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-16 21:35:46

Dla wywołania bash to trochę przesada. Chyba, że masz wiele bash binariów, takich jak Twój własny w ~ / bin, ale to również oznacza, że Twój kod zależy od $PATH, które mają w sobie odpowiednie rzeczy.

Jest przydatny do takich rzeczy jak python chociaż. Istnieją skrypty i środowiska opakowujące, które prowadzą do użycia alternatywnych binariów python.

Ale nic nie jest stracone, używając dokładnej ścieżki do pliku binarnego, o ile jesteś pewien, że jest to plik binarny, którego naprawdę chcesz.

 10
Author: Sean Perry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-06 20:12:17

Istnieje wiele systemów, które nie mają Basha w /bin, FreeBSD i OpenBSD, aby wymienić tylko kilka. Jeśli twój skrypt ma być przenośny dla wielu różnych uników, możesz użyć #!/usr/bin/env bash zamiast #!/bin/bash.

Zauważ, że to nie dotyczy sh; dla skryptów zgodnych z Bourne ' em używam wyłącznie #!/bin/sh, ponieważ myślę, że prawie każdy istniejący Uniks posiada sh w /bin.

 7
Author: James Ko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-28 03:52:07