Node.js jest obecnie bardzo popularny i pisałem na nim kilka skryptów. Niestety kompatybilność stanowi problem. Oficjalnie należy wywoływać interpreter Node.js node
, ale Debian i Ubuntu dostarczają nodejs
zamiast niego plik wykonywalny .
Chcę przenośnych skryptów, z którymi Node.js może pracować w jak największej liczbie sytuacji. Zakładając, że nazwa pliku brzmi foo.js
, naprawdę chcę, aby skrypt działał na dwa sposoby:
./foo.js
uruchamia skrypt, czy teżnode
czynodejs
jest$PATH
.node foo.js
uruchamia również skrypt (zakładając, że wywoływany jest interpreternode
)
Uwaga: Odpowiedzi xavierm02 i mnie to dwie odmiany skryptu polyglot. Nadal interesuje mnie rozwiązanie typu shebang, jeśli takie istnieje.
scripting
compatibility
node.js
tańczyć
źródło
źródło
node
skryptu lub stworzenie skryptu make, który modyfikuje shebang.alphacentauri
i tak dalej. Jeśli istnieje plik wykonywalny o nazwienodejs
, możesz być w 99% pewien, że jest to plik Node.js. Dlaczego nie wspierać zarównonodejs
inode
?Odpowiedzi:
Najlepsze, co wymyśliłem, to ten „dwuwierszowy shebang”, który tak naprawdę jest skryptem polyglot (powłoka Bourne'a / Node.js):
Pierwszą linią jest oczywiście szarpnięcie muszli Bourne'a. Node.js pomija każdy znaleziony shebang, więc jest to prawidłowy plik javascript, jeśli chodzi o Node.js.
Drugi wiersz wywołuje brak powłoki
:
z argumentem,//
a następnie wykonujenodejs
lubnode
z nazwą tego pliku jako parametrem.command -v
służywhich
do przenoszenia. Składnia podstawiania poleceń$(...)
nie jest ściśle Bourne, więc wybierz backsticks, jeśli uruchomisz to w latach 80.Node.js po prostu ocenia ciąg znaków
':'
, który jest jak no-op, a reszta linii jest analizowana jako komentarz.Reszta pliku to po prostu stary javascript. Podkładka kończy pracę po zakończeniu
exec
drugiej linii, więc reszta pliku nigdy nie jest odczytywana przez powłokę.Dzięki xavierm02 za inspirację i wszystkim komentującym za dodatkowe informacje!
źródło
':'
podejścia jest użycie// 2>/dev/null
(convm
robi): bash, to błąd (bash: //: Is a directory
), który przekierowanie2>/dev/null
cicho ignoruje; do JavaScript cała linia staje się komentarzem. Ponadto - i nie spodziewam się, że będzie to problem IRL -command
ma dziwactwo, w którym zgłasza również funkcje powłoki i aliasy-v
- nawet jeśli tak naprawdę ich nie wywołał. Tak więc, jeśli zdarzyło Ci się wyeksportować funkcje powłoki lub nawet aliasy (zakładającshopt -s expand_aliases
) o nazwienode
lubnodejs
, rzeczy mogą się zepsuć.mksh
,bash
,dash
i innych skorup w nowoczesnych systemach Unix i GNU.#!/usr/bin/env sh
zamiast#!/bin/sh
(na en.wikipedia.org/wiki/Shebang_%28Unix%29#Portability )#!/usr/bin/env sh
jako „bardziej przenośnymi”. Ten sam artykuł w Wikipedii mówi: „Działa to głównie dlatego, że ścieżka / usr / bin / env jest powszechnie używana w narzędziu env ...” To nie jest wspaniałe poparcie, i przypuszczam, że będziesz wpadał na systemy/usr/bin/env
częściej niż wpadasz na systemy bez/bin/sh
, jeśli w ogóle występuje jakakolwiek różnica częstotliwości.//bin/sh -c :; exec ...
to czystsza wersja drugiej linii?//bin/false
jest tym samym,/bin/false
z wyjątkiem tego, że drugi ukośnik przekształca go w komentarz do węzła i dlatego jest tutaj. Następnie||
oceniana jest prawa strona pierwszego .'which node || which nodejs'
z cudzysłowami zamiast cudzysłowów uruchamia węzeł i<<
przekazuje go, co jest po prawej stronie. Mógłbym użyć ogranicznika zaczynającego się//
tak, jak zrobił to dancek, zadziałałoby, ale uważam, że czystsze jest posiadanie tylko dwóch linii na początku, więc miałemtail -n +2 $0
plik czytany sam, z wyjątkiem dwóch pierwszych linii.A jeśli uruchomisz go w węźle, pierwszy wiersz zostanie rozpoznany jako shebang i zignorowany, a drugi to komentarz jednowierszowy.
(Najwyraźniej sed może być użyty do zastąpienia zawartości pliku wydruku ogona bez pierwszej i ostatniej linii )
Odpowiedz przed edycją:
Nie możesz robić tego, co chcesz, więc zamiast tego uruchom skrypt powłoki, stąd
#!/bin/sh
. Ten skrypt powłoki uzyska ścieżkę do pliku potrzebnego do uruchomienia węzła, to znaczywhich node || which nodejs
. Cytaty wsteczne są tutaj, aby zostały wykonane, więc'which node || which nodejs'
(z cudzysłowami zamiast cudzysłowów) po prostu wywołuje węzeł. Następnie po prostu nakarm go swoim skryptem<<
. Są__HERE__
to ograniczniki twojego skryptu. Aconsole.log('ok');
to przykład skryptu, który należy wymienić ze skryptu.źródło
<<'__HERE__'
.//bin/false
nie działa w moim środowisku MSYS i potrzebuję cudzysłowów za backtickami w miejscunode
zamieszkaniaC:\Program Files\...
. Tak, pracuję w okropnym środowisku ...//bin/false
nie działa również w systemie Mac OS X. Przepraszam, ale to już nie wydaje się zbyt przenośne.which
Polecenie nie jest przenośny.Jest to tylko problem w systemach opartych na Debianie, w których zasady zostały przezwyciężone.
Nie wiem, kiedy Fedora dostarczył plik binarny o nazwie nodejs, ale nigdy go nie widziałem. Pakiet nazywa się nodejs i instaluje binarny węzeł.
Po prostu użyj dowiązania symbolicznego, aby zastosować zdrowy rozsądek w systemach opartych na Debianie, a następnie możesz użyć zdrowego rozsądku. Zresztą inne osoby i tak będą używać zdrowych szejków, więc będziesz potrzebować tego dowiązania symbolicznego.
źródło
nodejs
plik wykonywalny , ale to nie wina Fedory. Przepraszam za wprowadzenie w błąd.#!/usr/bin/perl
. To powiedziawszy, nie jesteś zobowiązany do polubienia lub zastosowania moich sugestii. Pokój.Jeśli nie masz nic przeciwko utworzeniu małego
.sh
pliku, mam dla ciebie małe rozwiązanie. Możesz utworzyć mały skrypt powłoki, aby określić, który węzeł ma być wykonywalny, i użyć tego skryptu w swoim shebang:shebang.sh :
skrypt.js :
Zaznacz oba pliki wykonywalne i uruchom
./script.js
.W ten sposób unikasz skryptów polyglot. Nie sądzę, aby stosowanie wielu linii shebang było możliwe, chociaż wydaje się to dobrym pomysłem.
Chociaż rozwiązuje to problem tak, jak chcesz, wydaje się, że nikogo to nie obchodzi. Na przykład, uglifyjs i coffeescript zastosowań
#!/usr/bin/env node
, npm wykorzystuje skrypt jako punkt wyjścia, który ponownie wywołuje wyraźnie z nazwy pliku wykonywalnegonode
. Jestem użytkownikiem Ubuntu i nie wiedziałem o tym, ponieważ zawsze kompiluję węzeł. Rozważam zgłoszenie tego jako błędu.źródło
chmod +x
o skrypt sh ... więc równie dobrze możesz poprosić go o ustawienie zmiennej podającej lokalizację wykonywalnego węzła ...chmod +x
„d. Zgadzam się, że zmienna NODE jest lepsza niżwhich node || which nodejs
. Ale pytający chce zapewnić gotową obsługę, chociaż korzysta z niej wiele dużych projektów węzłów#!/usr/bin/env node
.Dla kompletności oto kilka innych sposobów wykonania drugiej linii:
Ale żadna nie ma żadnej przewagi nad wybraną odpowiedzią:
Ponadto, jeśli wiesz, że zostanie znaleziony jeden (
node
lubnodejs
nie oba), następujące działania:Ale to duże „jeśli”, więc myślę, że wybrana odpowiedź pozostaje najlepsza.
źródło
foobar // 2>/dev/null
o ilefoobar
nie jest to polecenie. Wiele narzędzi znalezionych w dowolnym systemie POSIX można uruchomić z//
argumentem.Rozumiem, że to nie odpowiada na pytanie, ale jestem przekonany, że pytanie zostało postawione w fałszywym założeniu.
Ubuntu się tutaj myli. Napisanie uniwersalnego shebang dla własnego skryptu nie zmieni innych pakietów, nad którymi nie masz kontroli, z których faktycznie korzysta standard
#!/usr/bin/env node
. System musi zapewnićnode
wPATH
jeśli chce żadnych skryptów kierowanych nodejs uruchomić na nim.Na przykład nawet
npm
pakiet dostarczony przez Ubuntu nie przepisuje shebangów w pakietach:źródło