Node.js est très populaire ces jours-ci et j'ai écrit quelques scripts dessus. Malheureusement, la compatibilité est un problème. Officiellement, l'interpréteur Node.js est censé être appelé node
, mais Debian et Ubuntu fournissent à la nodejs
place un exécutable appelé .
Je veux des scripts portables que Node.js puisse utiliser dans autant de situations que possible. En supposant que le nom de fichier soit foo.js
, je veux vraiment que le script s'exécute de deux manières:
./foo.js
exécute le script sinode
ounodejs
est dans$PATH
.node foo.js
exécute également le script (en supposant que l'interprète soit appelénode
)
Remarque: les réponses de xavierm02 et de moi-même sont deux variantes d'un script polyglotte. Je suis toujours intéressé par une solution pure de shebang, si une telle existe.
scripting
compatibility
node.js
dancek
la source
la source
node
pour votre script ou d'avoir une sorte de script de création qui modifie le shebang.alphacentauri
, etc. Si un exécutable est appelénodejs
, vous pouvez être sûr à 99% que c'est Node.js. Pourquoi ne pas soutenir les deuxnodejs
etnode
?Réponses:
Le meilleur que j'ai créé est ce script "à deux lignes" qui est vraiment un script polyglotte (Bourne shell / Node.js):
La première ligne est, évidemment, un shebang shell Bourne. Node.js contourne tous les shebang qu'il trouve, il s'agit donc d'un fichier javascript valide en ce qui concerne Node.js.
La deuxième ligne appelle le shell no-op
:
avec l'argument//
, puis s'exécutenodejs
ounode
avec le nom de ce fichier en tant que paramètre.command -v
est utilisé à la place dewhich
pour la portabilité. La syntaxe de substitution de commande$(...)
n'est pas strictement Bourne, optez donc pour des backticks si vous l'exécutez dans les années 1980.Node.js évalue simplement la chaîne
':'
, ce qui est comme un non-op, et le reste de la ligne est analysé comme un commentaire.Le reste du fichier est simplement du vieux javascript. Le sous-shell se ferme à la fin de la
exec
deuxième ligne, le reste du fichier n'est donc jamais lu par le shell.Merci à xavierm02 pour son inspiration et à tous les commentateurs pour des informations supplémentaires!
la source
':'
approche consiste à utiliser// 2>/dev/null
(ce qui est lenvm
cas): bash, c'est une erreur (bash: //: Is a directory
), que la redirection2>/dev/null
ignore discrètement; en JavaScript, toute la ligne devient un commentaire. En outre - et je ne m'attends pas à ce que ce soit un problème, IRL -command
présente une bizarrerie: il signale également les fonctions de shell et les alias-v
, même s'il ne les invoque pas réellement. Ainsi, si vous avez exporté des fonctions de shell ou même des alias (supposésshopt -s expand_aliases
) nommésnode
ou nommésnodejs
, les choses risquent de casser.mksh
,bash
,dash
et d' autres coquilles dans les systèmes Unix et GNU modernes.#!/usr/bin/env sh
place de#!/bin/sh
(par en.wikipedia.org/wiki/Shebang_%28Unix%29#Portability )#!/usr/bin/env sh
comme "plus portable". Ce même article de Wikipedia dit "Cela fonctionne principalement parce que le chemin / usr / bin / env est couramment utilisé pour l'utilitaire env ..." Ce n'est pas une approbation merveilleuse, et je suppose que vous rencontrerez des systèmes sans/usr/bin/env
plus vous rencontrez des systèmes sans/bin/sh
aucune différence de fréquence.//bin/sh -c :; exec ...
une version plus propre de la deuxième ligne?//bin/false
est la même chose que/bin/false
sauf que la deuxième barre oblique la transforme en un commentaire pour le noeud, et c'est pourquoi elle est ici. Ensuite, le côté droit du premier||
est évalué.'which node || which nodejs'
avec des guillemets au lieu de guillemets, lance le nœud et le<<
filme tout ce qui se trouve à droite. J'aurais pu utiliser un délimiteur commençant par "//
dancek", cela aurait fonctionné, mais je trouve plus propre de ne comporter que deux lignes au début, alors jetail -n +2 $0
lisais le fichier lui-même, à l'exception des deux premières lignes.Et si vous l'exécutez dans node, la première ligne est reconnue comme un shebang et ignorée et la seconde est un commentaire d'une ligne.
(Apparemment, sed pourrait être utilisé pour remplacer le contenu du fichier d'impression arrière sans les première et dernière lignes )
Répondre avant édition:
Vous ne pouvez pas faire ce que vous voulez, vous devez donc exécuter un script shell, d’où le fichier
#!/bin/sh
. Ce script shell obtiendra le chemin du fichier nécessaire à l'exécution du noeud, c'est-à-direwhich node || which nodejs
. Les citations arrières sont ici pour qu'il soit exécuté, ainsi'which node || which nodejs'
(avec les citations arrières au lieu des guillemets) appelle simplement noeud. Ensuite, vous alimentez simplement votre script avec<<
. Ce__HERE__
sont les délimiteurs de votre script. Etconsole.log('ok');
voici un exemple de script que vous devriez remplacer par votre script.la source
<<'__HERE__'
.//bin/false
cela ne fonctionne pas dans mon environnement MSYS, et j'ai besoin de guillemets sur les backticks en tant que mon lieu denode
résidenceC:\Program Files\...
. Oui, je travaille dans un environnement horrible ...//bin/false
ne fonctionne pas sur Mac OS X non plus. Je suis désolé, mais cela ne semble plus très portable.which
commande n'est pas non plus portable.Ce problème ne concerne que les systèmes basés sur Debian, où la politique a dépassé le sens.
Je ne sais pas quand Fedora a fourni un binaire appelé nodejs, mais je ne l'ai jamais vu. Le paquet s'appelle nodejs et installe un binaire appelé noeud.
Utilisez simplement un lien symbolique pour appliquer le bon sens à vos systèmes basés sur Debian, puis vous pourrez utiliser un shebang sain d'esprit. De toute façon, d'autres personnes utiliseront des shebangs sensés, vous aurez donc besoin de ce lien symbolique.
la source
nodejs
exécutable , mais ce n’est pas la faute de Fedora. Désolé pour déformer le fait.#!/usr/bin/perl
. Cela dit, vous n'êtes pas obligé d'aimer ou d'appliquer mes suggestions. Paix.Si vous voulez bien créer un petit
.sh
fichier, j'ai une petite solution pour vous. Vous pouvez créer un petit script shell pour déterminer le noeud exécutable à utiliser, et utiliser ce script dans votre shebang:shebang.sh :
script.js :
Marquez les deux exécutables et lancez
./script.js
.De cette façon, vous évitez les scripts polyglottes. Je ne pense pas qu'il soit possible d'utiliser plusieurs lignes de shebang, bien que cela semble être une bonne idée.
Même si cela résout le problème comme vous le souhaitez, il semble que personne ne s'en soucie. Par exemple, uglifyjs et coffeescript utilisent
#!/usr/bin/env node
, npm utilise un script shell comme point d’entrée, qui appelle à nouveau explicitement l’exécutable avec le nomnode
. Je suis un utilisateur Ubuntu et je ne le savais pas car je compile toujours des nœuds. J'envisage de signaler ceci comme un bug.la source
chmod +x
le script sh ... vous pouvez donc aussi leur demander de définir une variable donnant l'emplacement de leur nœud exécutable ...chmod +x
'd. Et je conviens qu’une variable NODE est meilleure quewhich node || which nodejs
. Mais l'enquêteur souhaite offrir une expérience immédiate, bien que de nombreux grands projets de nœuds l'utilisent#!/usr/bin/env node
.Par souci d’exhaustivité, voici deux autres façons de faire la deuxième ligne:
Mais ni l'un ni l'autre n'a aucun avantage sur la réponse choisie:
De plus, si vous saviez que l'un
node
ou l' autrenodejs
(mais pas les deux) serait trouvé, les travaux suivants:Mais c'est un gros "si", alors je pense que la réponse choisie reste la meilleure.
la source
foobar // 2>/dev/null
tant qu'ellefoobar
n'est pas une commande. Et bon nombre des utilitaires présents sur n’importe quel système POSIX peuvent être exécutés avec l’//
argument.Je comprends que cela ne répond pas à la question, mais je suis convaincu que la question est posée avec une fausse prémisse.
Ubuntu se trompe ici. Écrire un shebang universel pour votre propre script ne changera pas les autres packages sur lesquels vous n'avez aucun contrôle sur ceux qui utilisent le standard de facto
#!/usr/bin/env node
. Votre système doit fournirnode
enPATH
si elle le souhaite pour tous les scripts ciblant nodejs pour fonctionner sur elle.Par exemple, même le
npm
paquet fourni par Ubuntu ne réécrit pas les shebangs dans des paquets:la source