Gli script che devono essere eseguiti da un interprete normalmente hanno una linea shebang in alto per dire al sistema operativo come eseguirli.
Se hai uno script chiamato la foo
cui prima riga è #!/bin/sh
, il sistema leggerà quella prima riga ed eseguirà l'equivalente di /bin/sh foo
. Per questo motivo, la maggior parte degli interpreti è configurata per accettare il nome di un file di script come argomento della riga di comando.
Il nome dell'interprete che segue #!
deve essere un percorso completo; il sistema operativo non cercherà il tuo $PATH
per trovare l'interprete.
Se hai uno script da eseguire node
, il modo più ovvio per scrivere la prima riga è:
#!/usr/bin/node
ma non funziona se il node
comando non è installato in /usr/bin
.
Una soluzione alternativa comune consiste nell'usare il env
comando (che non era realmente destinato a questo scopo):
#!/usr/bin/env node
Se lo script viene chiamato foo
, il sistema operativo eseguirà l'equivalente di
/usr/bin/env node foo
Il env
comando esegue un altro comando il cui nome è dato sulla sua riga di comando, passando i seguenti argomenti a quel comando. Il motivo per cui viene utilizzato qui è che env
cercherà $PATH
il comando. Quindi, se node
è installato in /usr/local/bin/node
, e lo hai /usr/local/bin
nel tuo $PATH
, il env
comando verrà richiamato /usr/local/bin/node foo
.
Lo scopo principale del env
comando è eseguire un altro comando con un ambiente modificato, aggiungendo o rimuovendo le variabili di ambiente specificate prima di eseguire il comando. Ma senza argomenti aggiuntivi, esegue semplicemente il comando con un ambiente invariato, che è tutto ciò di cui hai bisogno in questo caso.
Ci sono alcuni svantaggi in questo approccio. La maggior parte dei moderni sistemi Unix lo hanno /usr/bin/env
, ma ho lavorato su sistemi più vecchi in cui il env
comando era installato in una directory diversa. Potrebbero esserci limitazioni su argomenti aggiuntivi che puoi passare usando questo meccanismo. Se l'utente non ha la directory contenente il node
comando $PATH
o ha chiamato un comando diverso node
, potrebbe richiamare il comando sbagliato o non funzionare affatto.
Altri approcci sono:
- Utilizzare una
#!
riga che specifica il percorso completo del node
comando stesso, aggiornando lo script secondo necessità per i diversi sistemi; o
- Invoca il
node
comando con il tuo script come argomento.
Vedi anche questa domanda (e la mia risposta ) per ulteriori discussioni sul #!/usr/bin/env
trucco.
Per inciso, sul mio sistema (Linux Mint 17.2), è installato come /usr/bin/nodejs
. Secondo le mie note, è cambiato da /usr/bin/node
a /usr/bin/nodejs
tra Ubuntu 12.04 e 12.10. Il #!/usr/bin/env
trucco non aiuta in questo (a meno che tu non abbia impostato un collegamento simbolico o qualcosa di simile).
AGGIORNAMENTO: Un commento di mtraceur dice (riformattato):
Una soluzione alternativa per il problema nodejs vs node è avviare il file con le seguenti sei righe:
#!/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
*/
Questo proverà prima nodejs
e poi proverà node
e stamperà i messaggi di errore solo se non vengono trovati entrambi. Una spiegazione esula dallo scopo di questi commenti, la lascio qui nel caso in cui aiuti qualcuno ad affrontare il problema poiché questa risposta ha sollevato il problema.
Non ho usato NodeJS ultimamente. La mia speranza è che il problema nodejs
vs. node
sia stato risolto negli anni trascorsi da quando ho pubblicato questa risposta per la prima volta. Su Ubuntu 18.04, il nodejs
pacchetto viene installato /usr/bin/nodejs
come collegamento simbolico a /usr/bin/node
. Su alcuni sistemi operativi precedenti (Ubuntu o Linux Mint, non sono sicuro di quale), c'era un nodejs-legacy
pacchetto che forniva node
un collegamento simbolico a nodejs
. Nessuna garanzia di avere tutti i dettagli corretti.
node