J’avais vu cette ligne #!/usr/bin/env node
au début de quelques exemples dans nodejs
et j’avais googlé sans trouver aucun sujet pouvant répondre à la raison de cette ligne.
La nature des mots rend la recherche pas si facile.
J’avais lu des livres javascript
et nodejs
récemment et je ne me souvenais pas de l’avoir vu dans aucun d’entre eux.
Si vous voulez un exemple, vous pourriez voir le tutoriel officiel de RabbitMQ
, 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’une ligne shebang : la toute première ligne d’un fichier texte brut exécutable sur des plates-formes de type Unix qui indique au système quel interpréteur transmettre ce fichier pour exécution , via la commande ligne suivant le #!
magique #!
préfixe (appelé shebang ).
Remarque: Windows ne prend pas en charge les lignes shebang , elles y sont donc ignorées . sous Windows, c’est uniquement l’ extension du nom de fichier d’ un fichier donné qui détermine ce que l’exécutable va interpréter. Cependant, vous en avez toujours besoin dans le contexte de npm
. [1]
La discussion générale suivante sur les lignes de shebang se limite aux plates-formes de type Unix:
Dans la discussion suivante, je suppose que le fichier contenant le code source à exécuter par Node.js est simplement nommé file
.
Vous avez besoin de cette ligne , si vous voulez appeler directement un fichier source Node.js, en tant qu’exécutable à part entière – cela suppose que le fichier a été marqué comme exécutable avec une commande telle que chmod +x ./file
, qui alors vous permet d’appeler le fichier avec, par exemple, ./file
, ou, s’il est situé dans l’un des répertoires répertoriés dans la variable $PATH
, simplement en tant que file
.
npm
fonction de la clé "bin"
dans le package d’un package.json
fichier package.json
; voir également cette réponse pour savoir comment cela fonctionne avec les paquets installés globalement . La note [1] montre comment cela est géré sous Windows. Vous n’avez pas besoin de cette ligne pour appeler un fichier explicitement via l’interpréteur de node
, par exemple, node ./file
Informations d’arrière-plan facultatives :
#!/usr/bin/env
est un moyen de spécifier un interprète de manière portable : en un mot, il dit: exécutez
partout où vous l’avez trouvé parmi les répertoires listés dans la variable $PATH
(et implicitement passer le chemin au fichier à scope de main).
Cela explique le fait qu’un interpréteur donné peut être installé à différents emplacements sur différentes plates-formes, ce qui est certainement le cas avec node
, le binary Node.js.
En revanche, l’emplacement de l’utilitaire env
lui-même peut se trouver au même endroit sur toutes les plates-formes, à savoir /usr/bin/env
– et la spécification du chemin complet d’un exécutable est requirejse dans une ligne shebang.
Notez que l’utilitaire POSIX env
est utilisé ici pour localiser par nom de fichier et exécuter un exécutable dans $PATH
.
Le véritable objective de env
est de gérer l’environnement pour une commande – voir les spécifications POSIX et la réponse utile de Keith Thompson .
Il est également intéressant de noter que Node.js fait une exception de syntaxe pour les lignes shebang, étant donné qu’elles ne sont pas du code JavaScript valide ( #
n’est pas un caractère de commentaire dans JavaScript, contrairement aux shells de type POSIX et autres interpréteurs).
[1] Dans l’intérêt de la cohérence entre plates-formes, npm
crée des fichiers wrapper *.cmd
(fichiers de commandes) sous Windows lors de l’installation d’exécutables spécifiés dans le fichier package.json
un package (via la propriété "bin"
). Essentiellement, ces fichiers batch wrapper imitent la fonctionnalité Unix shebang: ils invoquent explicitement le fichier cible avec l’exécutable spécifié dans la ligne shebang – vos scripts doivent donc inclure une ligne shebang même si vous ne souhaitez les exécuter que sous Windows – voir cette réponse à moi pour plus de détails.
Comme les fichiers *.cmd
peuvent être appelés sans l’extension .cmd
, cela permet une expérience multi-plateforme transparente: sous Windows et Unix, vous pouvez appeler une interface de ligne de commande installée par npm
par son nom d’origine sans extension.
Les scripts devant être exécutés par un interpréteur ont normalement une 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éteurs sont configurés pour accepter le nom d’un fichier 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 recherchera pas votre $PATH
pour trouver l’interpréteur.
Si vous avez un script à exécuter par node
, le moyen évident d’écrire la première ligne est:
#!/usr/bin/node
mais cela ne fonctionne pas si la commande node
n’est pas installée dans /usr/bin
.
Une solution courante consiste à utiliser la commande env
(qui n’était pas vraiment conçue à cet effet):
#!/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
recherche $PATH
pour la commande. Donc si node
est installé dans /usr/local/bin/node
et que vous avez /usr/local/bin
dans votre $PATH
, la commande env
invoquera /usr/local/bin/node foo
.
L’objective 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 certains inconvénients. La plupart des systèmes modernes de type Unix ont /usr/bin/env
, mais j’ai travaillé sur des systèmes plus anciens où la commande env
était installée dans un répertoire différent. Il peut y avoir des limitations sur les arguments supplémentaires que vous pouvez utiliser en utilisant ce mécanisme. Si l’utilisateur ne possède pas le répertoire contenant la commande node
dans $PATH
, ou s’il possède une commande différente appelée node
, il peut invoquer la mauvaise commande ou ne pas fonctionner du tout.
Les autres approches sont les suivantes:
#!
ligne qui spécifie le chemin d’access complet à la commande de node
elle-même, mettant à jour le script selon les besoins pour différents systèmes; ou node
avec votre script en tant qu’argument. Voir aussi cette question (et ma réponse ) pour plus de détails sur le tour #!/usr/bin/env
.
Incidemment, sur mon système (Linux Mint 17.2), il est installé sous /usr/bin/nodejs
. Selon mes notes, il est passé de /usr/bin/node
à /usr/bin/nodejs
entre Ubuntu 12.04 et 12.10. L’astuce #!/usr/bin/env
ne vous aidera pas (sauf si vous configurez un lien symbolique ou quelque chose de similaire).
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 “node” est 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 étant capable de trouver le programme d’interprétation de manière plus fiable.
Vous n’en avez pas forcément besoin, mais il est bon d’utiliser pour assurer la portabilité (et le professionnalisme)