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 nodejslugar.
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.jsejecuta el script si estánodeonodejsestá en$PATH.node foo.jstambié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

nodepara 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 ambosnodejsynode?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 ejecutanodejsonodecon el nombre de este archivo como parámetro.command -vse usa en lugar dewhichpara 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
execsegunda 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 quenvmhace): bash, es un error (bash: //: Is a directory), que la redirección2>/dev/nullignora silenciosamente; a JavaScript, toda la línea se convierte en un comentario. Además, y no espero que esto sea un problema, IRLcommandtiene 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) llamadonodeonodejs, las cosas podrían romperse.mksh,bash,dashy otros proyectiles en modernos sistemas Unix y GNU.#!/usr/bin/env shlugar de#!/bin/sh(por en.wikipedia.org/wiki/Shebang_%28Unix%29#Portability )#!/usr/bin/env shcomo "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/envmá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/falsees lo mismo que,/bin/falseexcepto 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 $0leer 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/falseno funciona en mi entorno MSYS, y necesito citas alrededor de los backticks ya que minodereside enC:\Program Files\.... Sí, trabajo en un ambiente horrible ...//bin/falsetampoco funciona en Mac OS X. Lo siento, pero esto ya no parece muy portátil.whichcomando 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
nodejsejecutable , 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
.sharchivo, 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 +xen 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
nodeonodejs(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/nullsiempre quefoobarno 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 proporcionarnodeenPATHsi lo desea para cualquier script de orientación nodejs a correr en él.Por ejemplo, ni siquiera el
npmpaquete provisto por Ubuntu reescribe shebangs en paquetes:fuente