Ich hatte diese Zeile #!/usr/bin/env node
am Anfang einiger Beispiele in gesehen nodejs
und gegoogelt, ohne ein Thema zu finden, das den Grund für diese Zeile beantworten könnte.
Die Art der Wörter macht die Suche nicht so einfach.
Ich würde einige lesen javascript
und nodejs
Bücher vor kurzem , und ich habe mich nicht daran erinnern es in einer von ihnen zu sehen.
Wenn Sie ein Beispiel möchten, können Sie das RabbitMQ
offizielle Tutorial sehen , sie haben es in fast allen Beispielen, hier ist eines davon:
#!/usr/bin/env node
var amqp = require('amqplib/callback_api');
amqp.connect('amqp://localhost', function(err, conn) {
conn.createChannel(function(err, ch) {
var ex = 'logs';
var msg = process.argv.slice(2).join(' ') || 'Hello World!';
ch.assertExchange(ex, 'fanout', {durable: false});
ch.publish(ex, '', new Buffer(msg));
console.log(" [x] Sent %s", msg);
});
setTimeout(function() { conn.close(); process.exit(0) }, 500);
});
Könnte mir jemand erklären, was diese Zeile bedeutet?
Was ist der Unterschied, wenn ich diese Zeile setze oder entferne? In welchen Fällen brauche ich es?
node
npm
ein Node.js-Quellenskript als (möglicherweise global verfügbare) CLI installieren möchten , müssen Sie eine Shebang-Zeile verwenden - undnpm
dies funktioniert sogar unter Windows. siehe meine noch einmal aktualisierte Antwort.Antworten:
#!/usr/bin/env node
ist eine Instanz einer Shebang-Zeile : Die allererste Zeile in einer ausführbaren Nur-Text-Datei auf Unix-ähnlichen Plattformen , die dem System über die Befehlszeile nach dem magischen#!
Präfix (genannt Shebang ) mitteilt, an welchen Interpreter diese Datei zur Ausführung übergeben werden soll. .Hinweis: Windows unterstützt keine Shebang-Zeilen , daher werden sie dort effektiv ignoriert . Unter Windows bestimmt nur die Dateinamenerweiterung einer bestimmten Datei , welche ausführbare Datei sie interpretiert. Sie benötigen sie jedoch weiterhin im Kontext von
npm
. [1]Die folgende allgemeine Diskussion über Shebang-Linien ist auf Unix-ähnliche Plattformen beschränkt:
In der folgenden Diskussion gehe ich davon aus, dass die Datei mit dem Quellcode zur Ausführung durch Node.js einfach benannt ist
file
.Sie BRAUCHEN diese Zeile , wenn Sie eine Node.js-Quelldatei direkt als eigenständige ausführbare Datei aufrufen möchten. Dies setzt voraus, dass die Datei mit einem Befehl wie "ausführbar" markiert wurde
chmod +x ./file
, mit dem Sie die Datei aufrufen können mit zum Beispiel./file
oder, wenn es sich in einem der in der$PATH
Variablen aufgelisteten Verzeichnisse befindet , einfach alsfile
.npm
basierend auf dem Wert des"bin"
Schlüssels des in einem Paket -package.json
Datei ; In dieser Antwort erfahren Sie auch, wie dies mit global installierten Paketen funktioniert . Fußnote [1] zeigt, wie dies unter Windows gehandhabt wird.Sie benötigen diese Zeile NICHT , um eine Datei explizit über den
node
Interpreter aufzurufen , z.node ./file
Optionale Hintergrundinformationen :
#!/usr/bin/env <executableName>
ist eine Möglichkeit , einen Interpreter portabel anzugeben: Kurz gesagt: Führen<executableName>
Sie ihn aus, wo immer Sie ihn (zuerst) in den in der$PATH
Variablen aufgeführten Verzeichnissen finden (und übergeben Sie ihm implizit den Pfad zur vorliegenden Datei).Dies erklärt die Tatsache, dass ein bestimmter Interpreter plattformübergreifend an verschiedenen Orten installiert werden kann, was bei
node
der Node.js-Binärdatei definitiv der Fall ist.Dagegen ist die Lage des
env
kann Dienstprogramm selbst herangezogen werden , in der seine gleichen Stelle über Plattformen, nämlich/usr/bin/env
- und die Spezifizierungs vollen zu einem ausführbaren Pfad ist erforderlich , in einer Linie shebang.Beachten Sie, dass POSIX - Dienstprogramm
env
wird umgewidmet hier nach Dateinamen zu finden und eine ausführbare Datei in dem ausführen$PATH
.Der eigentliche Zweck von
env
besteht darin, die Umgebung für einen Befehl zu verwalten - sieheenv
die POSIX-Spezifikation und die hilfreiche Antwort von Keith Thompson .Es ist auch erwähnenswert , dass Node.js eine Syntax macht Ausnahme für shebang Linien, da sie nicht gültig JavaScript - Code sind (
#
ist kein Kommentarzeichen in JavaScript, anders als in POSIX-wie Muscheln und andere Dolmetscher).[1] Im Interesse der plattformübergreifende Konsistenz,
npm
erstellt Wrapper*.cmd
- Dateien (Batch - Dateien) unter Windows , wenn in einem Paket der angegebenen ausführbare Dateien der Installationpackage.json
Datei (über die"bin"
Eigenschaft). Im Wesentlichen Dateien diese Wrapper Batch mimischen Unix shebang Funktionalität: Sie rufen Sie die Zieldatei explizit mit der ausführbaren Datei in der Shebang - Zeile angegeben - also Ihre Skripte auch eine Shebang - Zeile enthalten muss , wenn Sie jemals nur beabsichtigen , sie auf Windows laufen - siehe diese Antwort von mir für Details.Da können
*.cmd
Dateien ohne die aufgerufen werden.cmd
Dies sorgt für eine nahtlose plattformübergreifende Erfahrung: Unter Windows und Unix können Sie einenpm
installierte CLI effektiv unter ihrem ursprünglichen Namen ohne Erweiterung aufrufen .quelle
.cmd
und.py
festlegen, mit welchem Programm solche Dateien ausgeführt werden sollen. Unter Unix führt die Shebang-Zeile diese Funktion aus. Umnpm
auf allen unterstützten Plattformen arbeiten zu können, benötigen Sie die Shebang-Linie auch unter Windows.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: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):Wenn Ihr Skript aufgerufen wird
foo
, führt das Betriebssystem das Äquivalent von ausDer
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, dassenv
nach$PATH
dem Befehl gesucht wird . Wennnode
also in installiert/usr/local/bin/node
ist und Sie/usr/local/bin
in Ihrem haben$PATH
, wird derenv
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 derenv
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 , habennode
Befehl in$PATH
, oder hat einige andere Befehl aufgerufennode
, dann könnte es das falsche Kommando oder keine Arbeit überhaupt aufrufen.Andere Ansätze sind:
#!
Zeile, die den vollständigen Pfad zumnode
Befehl selbst angibt , und aktualisieren Sie das Skript nach Bedarf für verschiedene Systeme. odernode
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):
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 dasnodejs
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 einnodejs-legacy
Paket, dasnode
als Symlink zu bereitgestellt wurdenodejs
. Keine Garantie, dass ich alle Details richtig habe.quelle
nodejs
vs-node
Problem besteht darin, die Datei mit den folgenden sechs Zeilen zu starten: 1)#!/bin/sh -
, 2)':' /*-
3)test1=$(nodejs --version 2>&1) && exec nodejs "$0" "$@"
4)test2=$(node --version 2>&1) && exec node "$0" "$@"
, 5)exec printf '%s\n' "$test1" "$test2" 1>&2
6)*/
. Dies wird zuerst versuchennodejs
und dann versuchennode
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.-
in der#!
Leitung?-
In#!/bin/sh -
ist nur eine Gewohnheit, die sicherstellt, dass sich die Shell unter den extrem engen und unwahrscheinlichen Umständen richtig verhält, unter denen der Skriptname oder der relative Pfad, den die Shell sieht, mit a beginnt-
. (Ja, es sieht auch so aus, als ob jede Mainstream-Distribution wieder zusammengewachsen wärenode
als als primärer Name . Ich habe nicht nachgeforscht, um meinen Kommentar abzugeben, aber soweit ich weiß, wird nur der Stammbaum der Debian-Distribution verwendetnodejs
, und es sieht so aus als ob sie alle wieder zunode
Debian zurückgekehrt-x
und-v
", aber da die frühen Bourne-Likes nur das erste Argument als mögliche Optionen analysierten und die Shell mit diesen Optionen beginnt Es war missbräuchlich, die Shell dazu zu bringen, den Skriptnamen seit dem Original nicht mehr zu analysieren, und bleibt daher missbräuchlich, da das Verhalten aus Kompatibilitätsgründen in modernen Bourne-Likes beibehalten wird. Wenn ich mich an all meine Bourne-Geschichte und Portabilität erinnere, stimmt das.Kurze Antwort: Es ist der Weg zum Dolmetscher.
BEARBEITEN (lange Antwort): Der Grund, warum vor "Knoten" kein Schrägstrich steht, ist, dass Sie die Zuverlässigkeit von #! / Bin / nicht immer garantieren können. Das "/ env" -Bit macht das Programm plattformübergreifender, indem das Skript in einer geänderten Umgebung ausgeführt wird und das Interpreterprogramm zuverlässiger gefunden werden kann.
Sie brauchen es nicht unbedingt, aber es ist gut zu verwenden, um Portabilität (und Professionalität) zu gewährleisten.
quelle
/usr/bin/env
Bit ändert die Umgebung nicht. Es ist nur ein Befehl an einer (meistens) bekannten Stelle, der einen anderen als Argument angegebenen Befehl aufruft und danach sucht$PATH
. Der Punkt ist, dass für die#!
Zeile der vollständige Pfad zum aufgerufenen Befehl erforderlichnode
ist und Sie nicht unbedingt wissen, wo er installiert ist.