J'avais vu cette ligne #!/usr/bin/env node
au début de quelques exemples dans nodejs
et j’avais cherché sur Google sans trouver de sujet pouvant répondre à la raison de cette ligne.
La nature des mots rend la recherche difficile.
Je lisais récemment javascript
et nodejs
et je ne me souvenais pas de l'avoir vu dans aucun d'entre eux.
Si vous voulez un exemple, vous pouvez voir le RabbitMQ
officiel tutoriel , ils l'ont dans presque tous leurs exemples, en voici un:
#!/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);
});
Quelqu'un pourrait-il m'expliquer quelle est la signification de cette ligne?
Quelle est la différence si je mets ou supprime cette ligne? Dans quels cas en ai-je besoin?
#!/usr/bin/env node
est une instance d'un ligne Shebang: the la toute première ligne d'un fichier texte brut exécutable sur plates-formes de type Unix qui indique au système à quel interpréteur transférer ce fichier pour exécution, via la ligne de commande suivant la magie #!
préfixe (appelé Shebang).
Remarque: Windows fait pas prend en charge les lignes Shebang , elles sont donc efficaces. ignoré là; sous Windows, c'est uniquement l'extension du nom de fichier d'un fichier donné qui détermine quel exécutable l'interprétera. Cependant, vous en avez toujours besoin dans le contexte de npm
.[1]
La discussion générale suivante sur les lignes Shebang est limitée aux plates-formes de type Unix:
Dans la discussion suivante, je supposerai que le fichier contenant le code source à exécuter par Node.js est simplement nommé file
.
Vous BESOIN de cette ligne , si vous souhaitez appeler un fichier source Node.js directement, en tant qu'exécutable dans son propre droit - cela suppose que le fichier a été marqué comme exécutable avec une commande telle que chmod +x ./file
, qui vous permet ensuite d’appeler le fichier avec, par exemple, ./file
, ou, s’il se trouve dans l’un des répertoires énumérés dans le $PATH
variable, simplement comme file
.
npm
en fonction de la valeur de "bin"
clé dans un paquet package.json
fichier ; Voir aussi cette réponse pour savoir comment cela fonctionne avec globalement paquets installés. note de bas de page [1] montre comment cela est géré sous Windows.Vous n'avez PAS besoin de cette ligne pour appeler explicitement un fichier via l'interpréteur node
, par exemple, node ./file
Informations de base facultatives :
#!/usr/bin/env <executableName>
est un moyen de transférable spécifier un interprète: en un mot, il est écrit: execute <executableName>
_ où que vous trouviez (le premier) parmi les répertoires listés dans le $PATH
variable (et lui transmettra implicitement le chemin du fichier à traiter).
Cela explique le fait qu’un interprète donné peut être installé à différents endroits d’une plate-forme à l’autre, ce qui est certainement le cas de node
, le binaire Node.js.
En revanche, l'emplacement de l'utilitaire env
lui-même peut être considéré comme situé dans l'emplacement identique sur plusieurs plates-formes, à savoir /usr/bin/env
- et en spécifiant le chemin complet vers un exécutable est obligatoire dans une ligne Shebang.
Notez que l'utilitaire POSIX env
est en train d'être réutilisé ici pour localiser par nom de fichier et exécuter un exécutable dans le $PATH
.
Le but réel de env
est de gérer l'environnement pour une commande - voir la spécification POSIX de env
et réponse utile de Keith Thompson .
Il faut également noter que Node.js utilise une syntaxe exception pour les lignes Shebang, étant donné qu’elles ne sont pas du code JavaScript valide (#
n'est pas un caractère de commentaire en JavaScript, contrairement aux interpréteurs de type POSIX et autres interpréteurs).
[1] Dans l'intérêt de la cohérence entre plates-formes, npm
crée wrapper*.cmd
fichiers (fichiers de commandes) sous Windows lors de l’installation des exécutables spécifiés dans le fichier package.json
fichier (via le fichier "bin"
propriété). Essentiellement, ces fichiers de traitement par lots mimiques Fonctionnalités Unix Shebang: ils invoquent explicitement le fichier cible avec l’exécutable spécifié dans la ligne Shebang - ainsi, vos scripts doivent inclure une ligne Shebang même si vous avez toujours l'intention de les exécuter sous Windows - voir cette réponse à moi pour plus de détails.
Puisque *.cmd
les fichiers peuvent être appelés sans le .cmd
extension, cela permet une expérience multi-plateforme transparente: sous Windows et Unix, vous pouvez effectivement appeler une CLI installée par npm
- par son nom d'origine, sans extension.
Les scripts qui doivent être exécutés par un interprète ont normalement un ligne Shebang en haut pour indiquer au système d'exploitation comment les exécuter.
Si vous avez un script nommé foo
dont la première ligne est #!/bin/sh
, le système lira cette première ligne et exécutera l’équivalent de /bin/sh foo
. De ce fait, la plupart des interprètes sont configurés pour accepter le nom d'un fichier de script en tant qu'argument de ligne de commande.
Le nom de l'interprète suivant le #!
doit être un chemin complet; le système d'exploitation ne cherchera pas votre $PATH
pour trouver l'interprète.
Si vous avez un script à exécuter par node
, la manière évidente d'écrire la première ligne est la suivante:
#!/usr/bin/node
mais cela ne fonctionne pas si la commande node
n'est pas installée dans /usr/bin
.
Une solution de contournement courante consiste à utiliser la commande env
(qui n'était pas vraiment à cette fin):
#!/usr/bin/env node
Si votre script s'appelle foo
, le système d'exploitation fera l'équivalent de
/usr/bin/env node foo
La commande env
exécute une autre commande dont le nom est donné sur sa ligne de commande, en transmettant les arguments suivants à cette commande. La raison pour laquelle il est utilisé ici est que env
cherchera $PATH
pour la commande. Donc, si node
est installé dans /usr/local/bin/node
, et tu as /usr/local/bin
dans votre $PATH
, la commande env
invoquera /usr/local/bin/node foo
.
Le but principal de la commande env
est d’exécuter une autre commande avec un environnement modifié, en ajoutant ou en supprimant des variables d’environnement spécifiées avant d’exécuter la commande. Mais sans arguments supplémentaires, il exécute simplement la commande avec un environnement inchangé, ce qui est tout ce dont vous avez besoin dans ce cas.
Cette approche présente quelques inconvénients. La plupart des systèmes de type Unix modernes ont /usr/bin/env
, mais j’ai travaillé sur des systèmes plus anciens où la commande env
était installée dans un autre répertoire. Il peut y avoir des limites aux arguments supplémentaires que vous pouvez transmettre à l'aide de ce mécanisme. Si l'utilisateur ne possède pas le répertoire contenant la commande node
dans $PATH
, ou a une commande différente appelée node
, elle pourrait alors invoquer la mauvaise commande ou ne pas fonctionner du tout.
Les autres approches sont:
#!
ligne qui spécifie le chemin complet de la commande node
elle-même, en mettant à jour le script selon les besoins pour différents systèmes; ounode
avec votre script comme argument.Voir aussi cette question (et ma réponse ) pour plus d'informations sur le #!/usr/bin/env
tour.
Incidemment, sur mon système (Linux Mint 17.2), il est installé en tant que /usr/bin/nodejs
. Selon mes notes, il a changé de /usr/bin/node
à /usr/bin/nodejs
entre Ubuntu 12.04 et 12.10. Le #!/usr/bin/env
Cette astuce ne vous aidera pas (sauf si vous configurez un lien symbolique ou quelque chose de similaire).
UPDATE: Un commentaire de mtraceur dit (reformaté):
Une solution de contournement pour le problème nodejs vs node consiste à démarrer le fichier avec les six lignes suivantes:
#!/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 */
Ceci va d’abord essayer
nodejs
, puisnode
, et n’afficher que les messages d’erreur si les deux ne sont pas trouvés. Une explication est hors de portée de ces commentaires, je la laisse simplement ici au cas où cela aiderait quelqu'un à résoudre le problème, puisque cette réponse a soulevé le problème.
Je n'ai pas utilisé NodeJS ces derniers temps. Mon espoir est que le problème nodejs
vs node
a été résolu dans les années écoulées depuis que j'ai posté cette réponse pour la première fois. Sur Ubuntu 18.04, le paquet nodejs
installe /usr/bin/nodejs
comme lien symbolique vers /usr/bin/node
. Sur certains systèmes d'exploitation antérieurs (Ubuntu ou Linux Mint, je ne sais pas lequel), il y avait un nodejs-legacy
paquet qui a fourni node
sous forme de lien symbolique vers nodejs
. Aucune garantie que j'ai tous les détails du droit.
Réponse courte: c'est le chemin de l'interprète.
EDIT (Réponse longue): La raison pour laquelle il n'y a pas de barre oblique avant "noeud" est parce que vous ne pouvez pas toujours garantir la fiabilité de #!/Bin /. Le bit "/ env" rend le programme plus multi-plateforme en exécutant le script dans un environnement modifié et en permettant de trouver le programme interprète de manière plus fiable.
Vous n'en avez pas nécessairement besoin, mais il est bon de l'utiliser pour assurer la portabilité (et le professionnalisme)