Node.js es muy popular en estos días y he estado escribiendo algunos scripts en él. Lamentablemente, la compatibilidad es un problema. Oficialmente, se supone que se llama al intérprete Node.js node
, pero Debian y Ubuntu envían un ejecutable llamado en su nodejs
lugar.
Quiero scripts portátiles con los que Node.js pueda trabajar en tantas situaciones como sea posible. Suponiendo que el nombre de archivo es foo.js
, realmente quiero que el script se ejecute de dos maneras:
./foo.js
ejecuta el script si estánode
onodejs
está en$PATH
.node foo.js
también ejecuta el script (suponiendo que se llama al intérpretenode
)
Nota: Las respuestas de xavierm02 y de mí mismo son dos variaciones de un script políglota. Todavía estoy interesado en una solución pura shebang, si existe.
scripting
compatibility
node.js
dancek
fuente
fuente
node
para su secuencia de comandos o tener una especie de secuencia de comandos de creación que modifique el shebang.alphacentauri
. Si hay un ejecutable llamadonodejs
, puede estar 99% seguro de que es Node.js. ¿Por qué no apoyar a ambosnodejs
ynode
?Respuestas:
Lo mejor que se me ocurrió es este "shebang de dos líneas" que realmente es un script políglota (Bourne shell / Node.js):
La primera línea es, obviamente, un shebang de shell Bourne. Node.js omite cualquier shebang que encuentre, por lo que este es un archivo javascript válido en lo que respecta a Node.js.
La segunda línea llama al shell no-op
:
con el argumento//
y luego se ejecutanodejs
onode
con el nombre de este archivo como parámetro.command -v
se usa en lugar dewhich
para portabilidad. La sintaxis de sustitución de comandos$(...)
no es estrictamente Bourne, así que opte por backticks si ejecuta esto en la década de 1980.Node.js solo evalúa la cadena
':'
, que es como un no-op, y el resto de la línea se analiza como un comentario.El resto del archivo es simplemente javascript antiguo. El subshell se cierra después de completar la
exec
segunda línea, por lo que el resto nunca lee el shell.¡Gracias a xavierm02 por inspiración y a todos los comentaristas por información adicional!
fuente
':'
enfoque es usar// 2>/dev/null
(que es lo quenvm
hace): bash, es un error (bash: //: Is a directory
), que la redirección2>/dev/null
ignora silenciosamente; a JavaScript, toda la línea se convierte en un comentario. Además, y no espero que esto sea un problema, IRLcommand
tiene una peculiaridad en la que también informa sobre las funciones de shell y los alias-v
, aunque en realidad no los invocaría. Por lo tanto, si ha exportado funciones de shell o incluso alias (suponiendoshopt -s expand_aliases
) llamadonode
onodejs
, las cosas podrían romperse.mksh
,bash
,dash
y otros proyectiles en modernos sistemas Unix y GNU.#!/usr/bin/env sh
lugar de#!/bin/sh
(por en.wikipedia.org/wiki/Shebang_%28Unix%29#Portability )#!/usr/bin/env sh
como "más portátil". Ese mismo artículo de Wikipedia dice "Esto funciona principalmente porque la ruta / usr / bin / env se usa comúnmente para la utilidad env ..." Eso no es un respaldo maravilloso, y supongo que te encontrarás con sistemas sin/usr/bin/env
más frecuencia que te encuentras con sistemas sin/bin/sh
, si hay alguna diferencia en frecuencia.//bin/sh -c :; exec ...
una versión más limpia de la segunda línea?//bin/false
es lo mismo que,/bin/false
excepto que la segunda barra oblicua lo transforma en un comentario para el nodo, y es por eso que está aquí. Luego,||
se evalúa el lado derecho del primero .'which node || which nodejs'
con comillas inversas en lugar de comillas, inicia el nodo y lo<<
alimenta lo que esté a la derecha. Podría haber usado un delimitador comenzando//
como dancek, hubiera funcionado, pero me parece más limpio tener solo dos líneas al principio, así que solíatail -n +2 $0
leer el archivo solo, excepto las dos primeras líneas.Y si lo ejecuta en el nodo, la primera línea se reconoce como un shebang y se ignora y la segunda es un comentario de una línea.
(Aparentemente, sed podría usarse para reemplazar el contenido del archivo Print de cola sin la primera y última línea )
Responda antes de editar:
No puedes hacer lo que quieres, así que lo que haces es ejecutar un script de shell, de ahí el
#!/bin/sh
. Ese script de shell obtendrá la ruta del archivo necesario para ejecutar el nodo, es decirwhich node || which nodejs
. Las comillas inversas están aquí para que se ejecuten, por lo que'which node || which nodejs'
(con las comillas inversas en lugar de las comillas) simplemente llama al nodo. Luego, simplemente alimente su script con él<<
. El__HERE__
son los delimitadores de secuencia de comandos de la suya. Y elconsole.log('ok');
es un ejemplo de secuencia de comandos que debe reemplazar con su secuencia de comandos.fuente
<<'__HERE__'
.//bin/false
no funciona en mi entorno MSYS, y necesito citas alrededor de los backticks ya que minode
reside enC:\Program Files\...
. Sí, trabajo en un ambiente horrible ...//bin/false
tampoco funciona en Mac OS X. Lo siento, pero esto ya no parece muy portátil.which
comando tampoco es portátil.Esto es solo un problema en los sistemas basados en Debian, donde la política superó el sentido.
No sé cuándo Fedora proporcionó un binario llamado nodejs, pero nunca lo vi. El paquete se llama nodejs e instala un binario llamado nodo.
Simplemente use un enlace simbólico para aplicar el sentido común a sus sistemas basados en Debian, y luego puede usar un shebang sano. Otras personas usarán shebangs sanos de todos modos, por lo que necesitarás ese enlace simbólico.
fuente
nodejs
ejecutable , pero eso no es culpa de Fedora. Perdón por tergiversar el hecho.#!/usr/bin/perl
. Dicho esto, no está obligado a dar me gusta o aplicar mis sugerencias. Paz.Si no le importa crear un pequeño
.sh
archivo, tengo una pequeña solución para usted. Puede crear un pequeño script de shell para determinar qué nodo ejecutable usar, y usar este script en su shebang:shebang.sh :
script.js :
Marque ambos ejecutables y ejecute
./script.js
.De esta manera, evita las secuencias de comandos políglotas. No creo que sea posible usar varias líneas shebang, aunque parece una buena idea.
Aunque esto resuelve el problema de la manera que desea, parece que a nadie le importa esto. Por ejemplo, uglifyjs y coffeescript usa
#!/usr/bin/env node
, npm usa un script de shell como punto de entrada, que nuevamente llama al ejecutable explícitamente con nombrenode
. Soy un usuario de Ubuntu, y no sabía esto, ya que siempre compilo el nodo. Estoy considerando reportar esto como un error.fuente
chmod +x
en el guión sh ... por lo que también podría pedir que establecer una variable que da la ubicación de su archivo ejecutable nodo ...chmod +x
'd. Y estoy de acuerdo en que una variable NODE es mejor quewhich node || which nodejs
. Pero el investigador quiere proporcionar una experiencia lista para usar, aunque muchos proyectos importantes de nodos simplemente lo utilizan#!/usr/bin/env node
.Solo para completar, aquí hay un par de otras formas de hacer la segunda línea:
Pero tampoco tiene ninguna ventaja sobre la respuesta seleccionada:
Además, si sabía que se encontraría uno
node
onodejs
(pero no ambos), lo siguiente funciona:Pero ese es un gran "si", así que creo que la respuesta seleccionada sigue siendo la mejor.
fuente
foobar // 2>/dev/null
siempre quefoobar
no sea un comando. Y muchas de las utilidades que se encuentran en cualquier sistema POSIX se pueden ejecutar con el//
argumento.Entiendo que esto no responde la pregunta, pero estoy convencido de que la pregunta se hace con una premisa falsa.
Ubuntu está equivocado aquí. Escribir un shebang universal para su propio script no cambiará otros paquetes sobre los que no tiene control y que usan el estándar de facto
#!/usr/bin/env node
. Su sistema debe proporcionarnode
enPATH
si lo desea para cualquier script de orientación nodejs a correr en él.Por ejemplo, ni siquiera el
npm
paquete provisto por Ubuntu reescribe shebangs en paquetes:fuente