Skrypty, które mają być wykonane przez tłumacza, zwykle mają linię szarpnięcia u góry która informuje system operacyjny, jak je wykonać.
Jeśli masz skrypt o nazwie, foo
którego pierwsza linia to #!/bin/sh
, system odczyta tę pierwszą linię i wykona odpowiednik /bin/sh foo
. Z tego powodu większość interpreterów jest skonfigurowana tak, aby akceptować nazwę pliku skryptu jako argument wiersza poleceń.
Nazwa tłumacza występująca po #!
musi być pełną ścieżką; system operacyjny nie będzie szukał twojego $PATH
tłumacza.
Jeśli masz skrypt do wykonania node
, oczywistym sposobem napisania pierwszej linii jest:
#!/usr/bin/node
ale to nie działa, jeśli node
polecenie nie jest zainstalowane w/usr/bin
.
Typowym obejściem jest użycie env
polecenia (które tak naprawdę nie było przeznaczone do tego celu):
#!/usr/bin/env node
Jeśli Twój skrypt zostanie wywołany foo
, system operacyjny wykona odpowiednik
/usr/bin/env node foo
env
Polecenie wykonuje inną komendę, którego nazwa podana jest w linii poleceń, przechodząc żadnych następujące argumenty do tego polecenia. Powodem jest to, że env
wyszuka $PATH
polecenie. Więc jeśli node
jest zainstalowany /usr/local/bin/node
i masz /usr/local/bin
w swoim $PATH
, env
polecenie zostanie wywołane /usr/local/bin/node foo
.
Głównym celem env
polecenia jest wykonanie innego polecenia w zmodyfikowanym środowisku, dodanie lub usunięcie określonych zmiennych środowiskowych przed uruchomieniem polecenia. Ale bez dodatkowych argumentów, po prostu wykonuje polecenie w niezmienionym środowisku, co jest wszystkim, czego potrzebujesz w tym przypadku.
Takie podejście ma pewne wady. Większość nowoczesnych systemów typu Unix ma /usr/bin/env
, ale pracowałem na starszych systemach, w których env
polecenie zostało zainstalowane w innym katalogu. Mogą istnieć ograniczenia dotyczące dodatkowych argumentów, które można przekazać za pomocą tego mechanizmu. Jeśli użytkownik nie ma katalogu zawierającego node
polecenie $PATH
lub ma inną komendę o nazwienode
, może wywołać niewłaściwe polecenie lub w ogóle nie działać.
Inne podejścia to:
- Użyj
#!
wiersza określającego pełną ścieżkę do samego node
polecenia, aktualizując skrypt zgodnie z potrzebami dla różnych systemów; lub
- Wywołaj
node
polecenie ze swoim skryptem jako argumentem.
Zobacz także to pytanie (i moją odpowiedź ), aby uzyskać więcej informacji na temat#!/usr/bin/env
sztuczce.
Nawiasem mówiąc, w moim systemie (Linux Mint 17.2) jest zainstalowany jako /usr/bin/nodejs
. Według moich notatek zmieniło się z /usr/bin/node
na /usr/bin/nodejs
między Ubuntu 12.04 a 12.10. Ta #!/usr/bin/env
sztuczka nie pomoże w tym (chyba że skonfigurujesz łącze symboliczne lub coś podobnego).
AKTUALIZACJA: komentarz mtraceur mówi (przeformatowano):
Obejście problemu nodejs vs węzeł polega na uruchomieniu pliku z następującymi sześcioma wierszami:
#!/bin/sh -
':' /*-
test1=$(nodejs --version 2>&1) && exec nodejs "$0" "$@"
test2=$(node --version 2>&1) && exec node "$0" "$@"
exec printf '%s\n' "$test1" "$test2" 1>&2
*/
To najpierw spróbuje, nodejs
a następnie spróbuje node
i wydrukuje komunikaty o błędach tylko wtedy, gdy oba z nich nie zostaną znalezione. Wyjaśnienie jest poza zakresem tych komentarzy, zostawiam je tutaj na wypadek, gdyby pomogło komukolwiek poradzić sobie z problemem, ponieważ ta odpowiedź przyniosła problem.
Ostatnio nie korzystałem z NodeJS. Mam nadzieję, że problem nodejs
z node
wersją został rozwiązany w latach, które minęły, odkąd po raz pierwszy opublikowałem tę odpowiedź. W systemie Ubuntu 18.04 nodejs
pakiet instaluje się /usr/bin/nodejs
jako łącze symboliczne do /usr/bin/node
. W niektórych wcześniejszych systemach operacyjnych (Ubuntu lub Linux Mint, nie jestem pewien który) istniał nodejs-legacy
pakiet, który był dostarczany node
jako dowiązanie symboliczne do nodejs
. Nie ma gwarancji, że wszystkie szczegóły są prawidłowe.
node