Los scripts que deben ser ejecutados por un intérprete normalmente tienen una línea shebang en la parte superior para indicarle al sistema operativo cómo ejecutarlos.
Si tiene un script llamado foo
cuyo primera línea #!/bin/sh
, el sistema leerá esa primera línea y ejecutará el equivalente de /bin/sh foo
. Debido a esto, la mayoría de los intérpretes están configurados para aceptar el nombre de un archivo de secuencia de comandos como argumento de línea de comandos.
El nombre del intérprete que sigue al #!
a debe ser una ruta completa; el sistema operativo no buscará su $PATH
intérprete.
Si tiene un script para que lo ejecute node
, la forma obvia de escribir la primera línea es:
#!/usr/bin/node
pero eso no funciona si el node
comando no está instalado en /usr/bin
.
Una solución alternativa común es usar el env
comando (que no era realmente destinado a este propósito):
#!/usr/bin/env node
Si se llama a su script foo
, el sistema operativo hará el equivalente a
/usr/bin/env node foo
El env
comando ejecuta otro comando cuyo nombre se da en su línea de comando, pasando los siguientes argumentos a ese comando. La razón por la que se usa aquí es que env
buscará $PATH
el comando. Entonces, si node
está instalado /usr/local/bin/node
y tiene /usr/local/bin
en su $PATH
, el env
comando se invocará /usr/local/bin/node foo
.
El propósito principal del env
comando es ejecutar otro comando con un entorno modificado, agregando o eliminando variables de entorno especificadas antes de ejecutar el comando. Pero sin argumentos adicionales, simplemente ejecuta el comando con un entorno sin cambios, que es todo lo que necesita en este caso.
Hay algunos inconvenientes en este enfoque. La mayoría de los sistemas modernos tipo Unix lo han hecho /usr/bin/env
, pero trabajé en sistemas más antiguos donde el env
comando se instaló en un directorio diferente. Puede haber limitaciones en los argumentos adicionales que puede pasar usando este mecanismo. Si el usuario no tiene el directorio que contiene el node
comando $PATH
, o tiene un comando diferente llamado node
, entonces podría invocar el comando incorrecto o no funcionar en absoluto.
Otros enfoques son:
- Usar una
#!
línea que especifique la ruta completa al node
comando en sí, actualizando el script según sea necesario para diferentes sistemas; o
- Invoque el
node
comando con su secuencia de comandos como argumento.
Consulte también esta pregunta (y mi respuesta ) para obtener más información sobre la#!/usr/bin/env
truco.
Por cierto, en mi sistema (Linux Mint 17.2), está instalado como /usr/bin/nodejs
. Según mis notas, cambió de /usr/bin/node
a /usr/bin/nodejs
entre Ubuntu 12.04 y 12.10. los#!/usr/bin/env
truco no ayudará con eso (a menos que configure un enlace simbólico o algo similar).
ACTUALIZACIÓN: Un comentario de mtraceur dice (reformateado):
Una solución para el problema de nodejs vs node es iniciar el archivo con las siguientes seis líneas:
#!/bin/sh -
':' /*-
test1=$(nodejs --version 2>&1) && exec nodejs "$0" "$@"
test2=$(node --version 2>&1) && exec node "$0" "$@"
exec printf '%s\n' "$test1" "$test2" 1>&2
*/
Esto primero intentará nodejs
y luego intentará node
, y solo imprimirá los mensajes de error si no se encuentran ambos. Una explicación está fuera del alcance de estos comentarios, solo la dejo aquí en caso de que ayude a alguien a lidiar con el problema, ya que esta respuesta planteó el problema.
No he usado NodeJS últimamente. Mi esperanza es que el problema de nodejs
vs. node
se haya resuelto en los años desde que publiqué esta respuesta por primera vez. En Ubuntu 18.04, el nodejs
paquete se instala /usr/bin/nodejs
como un enlace simbólico a /usr/bin/node
. En algunos sistemas operativos anteriores (Ubuntu o Linux Mint, no estoy seguro de cuál), había un nodejs-legacy
paquete que se proporcionaba node
como enlace simbólico a nodejs
. No hay garantía de que tenga todos los detalles correctos.
node