Que fait exactement "/usr/bin/env node" au début des fichiers nodes?

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 qui pourrait répondre à la raison de cette ligne.

la nature des mots ne rend pas la recherche facile.

j'avais lu récemment des livres javascript et nodejs et je ne m'en souvenais pas.

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 ce que signifie cette ligne?

quelle différence cela fait-il si je mets ou retire cette ligne? Dans quels cas ai-je besoin?

56
demandé sur mklement0 2015-11-04 00:55:07

3 réponses

#!/usr/bin/env node est une instance d'un ligne shebang : première ligne dans un fichier exécutable fichier de texte brut sur les plateformes de type Unix qui indique au système qu'interprète pour transmettre ce fichier à des fins d'exécution , via la ligne de commande à la suite de la magie #! préfixe (appelé shebang ).

Note: Windows does not support shebang lines , de sorte qu'ils sont effectivement ignored là; sur Windows, il est uniquement une extension de fichier de fichier d'un fichier donné qui détermine ce que l'exécutable va l'interpréter. cependant, vous avez encore besoin d'eux dans le contexte de npm . [1]

, discussion générale de shebang lines est limité aux plates-formes Unix-like:

dans la discussion suivante, je supposerai que le fichier contenant le code source pour l'exécution par noeud.js est simplement appelé file .

  • vous besoin de cette ligne , si vous voulez invoquer un noeud.js source file directement , 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 permet d'invoquer le fichier avec, par exemple, ./file , ou, s'il est situé dans l'un des répertoires listés dans la $PATH variable, simplement comme file .

    • spécifiquement, vous avez besoin d'une ligne shebang pour créer clic basé sur le noeud.js Source files dans le cadre d'un npm package , avec le CLI(s) à être installé par npm basé sur la valeur de la touche "bin" dans le fichier package.json d'un paquet ; voir aussi cette réponse pour savoir comment cela fonctionne avec globalement paquets installés. La note de bas de page [1] montre comment cela est géré sur Windows.
  • Vous n'ont PAS besoin de cette ligne pour appeler un fichier explicitement par l'intermédiaire de l'interprète node , p.ex. node ./file


Informations générales facultatives :

#!/usr/bin/env <executableName> est un moyen de de façon portative spécifiant un interpréteur: en un mot, il dit: exécuter <executableName> partout où vous le trouvez parmi les répertoires listés dans la variable $PATH (et lui passer implicitement le chemin vers le le fichier à la main).

cela explique le fait qu'un interpréteur donné peut être installé à différents endroits à travers les plateformes, ce qui est certainement le cas avec node , le noeud.js binaire.

en revanche, l'emplacement de l'utilité env elle-même peut être considérée comme étant dans le même emplacement à travers les plates - formes, à savoir /usr/bin/env - et en précisant le complet chemin vers un l'exécutable est requis dans une ligne de 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 véritable but de env est de gérer l'environnement pour une commande-voir env 's POSIX spec et la réponse utile de Keith Thompson .


il est également intéressant de noter ce noeud.js fait une syntaxe exception pour les lignes de shebang, étant donné qu'elles ne sont pas un code JavaScript valide ( # n'est pas un caractère de commentaire en JavaScript, contrairement aux shells de type POSIX et autres interprètes).


[1] dans l'intérêt de la cohérence entre les plates-formes, npm crée wrapper *.cmd fichiers (fichiers par lot) sur Windows lors de l'installation des exécutables spécifiés dans le fichier package.json d'un paquet (via la propriété "bin" ). Essentiellement, ces fichiers wrapper batch mimic Unix shebang fonctionnalité: ils invoquent le fichier cible explicitement avec l'exécutable spécifié dans la ligne de shebang - ainsi, vos scripts doivent inclure une ligne de shebang même si vous seulement jamais l'intention de les exécuter sur Windows - voir cette réponse de la mienne pour plus de détails.

Étant donné que les fichiers *.cmd peuvent être invoqués sans l'extension .cmd , cela permet une expérience multiplateforme sans faille: sous Windows et Unix, vous pouvez effectivement invoquer un CLI npm -installé par son nom d'origine, sans extension.

84
répondu mklement0 2017-06-10 03:14:02
Les Scripts

qui doivent ê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 . Pour cette raison, la plupart des interprètes sont configurés pour accepter le nom d'un fichier script comme argument de ligne de commande.

le le nom de l'interpréteur suivant le #! doit être un chemin complet; L'OS ne cherchera pas votre $PATH pour trouver l'interpréteur.

si vous avez un script à exécuter par node , la façon évidente 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 est d'utiliser la commande env (qui n'était pas vraiment prévu à cet effet):

#!/usr/bin/env node

si votre script s'appelle foo , L'OS fera l'équivalent de

/usr/bin/env node foo

la commande env exécute une autre commande dont le nom est indiqué sur sa ligne de commande, en passant tous les arguments suivants à cette commande. La raison pour laquelle il est utilisé ici est que env va chercher $PATH pour la commande. Donc si node est installé dans /usr/local/bin/node , et vous avez /usr/local/bin dans votre $PATH , le commandement 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 comporte certains inconvénients. La plupart des systèmes Unix modernes ont /usr/bin/env , mais j'ai travaillé sur des systèmes plus anciens où la commande env a été installée dans un répertoire différent. Il pourrait y avoir des limites sur les arguments supplémentaires que vous pouvez passer en utilisant ce mécanisme. Si l'utilisateur n'a pas le répertoire contenant la commande node dans $PATH , ou a une autre commande appelée node , alors il pourrait invoquer la mauvaise commande ou pas de travail du tout.

autres approches:

  • utilisez une ligne #! qui spécifie le chemin complet vers la commande node elle-même, en mettant à jour le script si nécessaire pour différents systèmes; ou
  • invoquez la commande node avec votre script comme argument.

Voir aussi cette question (et ma réponse ) pour plus discussion de la #!/usr/bin/env truc.

soit dit en passant, sur mon système (Linux Mint 17.2), il est installé comme /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 ne vous aidera pas avec cela (à moins que vous mettiez en place un lien symbolique ou quelque chose de similaire).

14
répondu Keith Thompson 2017-04-13 12:36:27

brève réponse: C'est le chemin vers l'interpréteur.

EDIT (longue réponse): La raison pour laquelle il n'y a pas de slash avant "node" est que vous ne pouvez pas toujours garantir la fiabilité de #!/bac. / Le bit "/ env " rend le programme plus multiplate-forme en exécutant le script dans un environnement modifié et en étant plus fiable pour trouver le programme interprète.

Vous n'avez pas nécessairement besoin, mais il est bon d'utiliser pour assurer la portabilité (et professionalism)

0
répondu Quantum 2015-11-03 22:01:11