Skripte, die von einem Interpreter ausgeführt werden sollen, haben normalerweise eine Shebang-Zeile oben, um dem Betriebssystem mitzuteilen, wie sie ausgeführt werden sollen.
Wenn Sie ein Skript mit dem Namen haben, foo
dessen erste Zeile lautet #!/bin/sh
, liest das System diese erste Zeile und führt das Äquivalent von aus /bin/sh foo
. Aus diesem Grund sind die meisten Interpreter so eingerichtet, dass sie den Namen einer Skriptdatei als Befehlszeilenargument akzeptieren.
Der Name des Interpreters #!
nach muss ein vollständiger Pfad sein. Das Betriebssystem sucht nicht $PATH
nach dem Interpreter.
Wenn Sie ein Skript haben, das ausgeführt werden soll node
, können Sie die erste Zeile auf folgende Weise schreiben:
#!/usr/bin/node
Das funktioniert aber nicht, wenn der node
Befehl nicht installiert ist /usr/bin
.
Eine übliche Problemumgehung besteht darin, den env
Befehl zu verwenden (der nicht wirklich für diesen Zweck vorgesehen war):
#!/usr/bin/env node
Wenn Ihr Skript aufgerufen wird foo
, führt das Betriebssystem das Äquivalent von aus
/usr/bin/env node foo
Der env
Befehl führt einen anderen Befehl aus, dessen Name in der Befehlszeile angegeben ist, und übergibt alle folgenden Argumente an diesen Befehl. Der Grund, warum es hier verwendet wird, ist, dass env
nach $PATH
dem Befehl gesucht wird . Wenn node
also in installiert /usr/local/bin/node
ist und Sie /usr/local/bin
in Ihrem haben $PATH
, wird der env
Befehl aufgerufen /usr/local/bin/node foo
.
Der Hauptzweck des env
Befehls besteht darin, einen anderen Befehl mit einer geänderten Umgebung auszuführen und bestimmte Umgebungsvariablen hinzuzufügen oder zu entfernen, bevor der Befehl ausgeführt wird. Ohne zusätzliche Argumente wird der Befehl jedoch nur in einer unveränderten Umgebung ausgeführt, was in diesem Fall alles ist, was Sie benötigen.
Dieser Ansatz weist einige Nachteile auf. Die meisten modernen Unix-ähnlichen Systeme haben /usr/bin/env
, aber ich habe auf älteren Systemen gearbeitet, auf denen der env
Befehl in einem anderen Verzeichnis installiert wurde. Möglicherweise gibt es Einschränkungen für zusätzliche Argumente, die Sie mit diesem Mechanismus übergeben können. Wenn der Benutzer nicht das das Verzeichnis enthalten , haben node
Befehl in $PATH
, oder hat einige andere Befehl aufgerufen node
, dann könnte es das falsche Kommando oder keine Arbeit überhaupt aufrufen.
Andere Ansätze sind:
- Verwenden Sie eine
#!
Zeile, die den vollständigen Pfad zum node
Befehl selbst angibt , und aktualisieren Sie das Skript nach Bedarf für verschiedene Systeme. oder
- Rufen Sie den
node
Befehl mit Ihrem Skript als Argument auf.
Siehe auch diese Frage (und meine Antwort ) für weitere Diskussionen über den #!/usr/bin/env
Trick.
Auf meinem System (Linux Mint 17.2) ist es übrigens installiert als /usr/bin/nodejs
. Nach meinen Notizen, änderte sie sich von /usr/bin/node
zu /usr/bin/nodejs
zwischen Ubuntu 12.04 und 12.10. Der #!/usr/bin/env
Trick hilft dabei nicht (es sei denn, Sie richten einen Symlink oder ähnliches ein).
UPDATE: Ein Kommentar von mtraceur sagt (neu formatiert):
Eine Problemumgehung für das Problem nodejs vs node besteht darin, die Datei mit den folgenden sechs Zeilen zu starten:
#!/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
*/
Dies wird zuerst versuchen nodejs
und dann versuchen node
und die Fehlermeldungen nur drucken, wenn beide nicht gefunden werden. Eine Erklärung liegt außerhalb des Rahmens dieser Kommentare. Ich lasse sie nur hier, falls sie jemandem hilft, mit dem Problem umzugehen, da diese Antwort das Problem angesprochen hat.
Ich habe NodeJS in letzter Zeit nicht verwendet. Ich hoffe, dass das Problem nodejs
vs. node
in den Jahren, seit ich diese Antwort zum ersten Mal gepostet habe, behoben wurde. Unter Ubuntu 18.04 wird das nodejs
Paket /usr/bin/nodejs
als Symlink zu installiert /usr/bin/node
. Auf einigen früheren Betriebssystemen (Ubuntu oder Linux Mint, ich bin mir nicht sicher, welches) gab es ein nodejs-legacy
Paket, das node
als Symlink zu bereitgestellt wurde nodejs
. Keine Garantie, dass ich alle Details richtig habe.
node