Hashbang apropriado para scripts Node.js

95

Estou tentando criar um script para node.js que funcionará em vários ambientes. Particularmente para mim, estou alternando entre o OS X e o Ubuntu. No primeiro, o Node é instalado como node, mas no segundo ele é nodejs. No início do meu script, posso ter:

#!/usr/bin/env node

ou

#!/usr/bin/env nodejs

Prefiro que o script seja executado como um executável para qualquer ambiente, desde que o nó esteja instalado, em vez de ter um ou outro especificando o comando ( ./script-name.jsvs. node script-name.js).

Existe alguma maneira de especificar um hashbang de backup ou que seja compatível em ambos os casos para node.js?

Pílulas de explosão
fonte
você poderia fazer um script de shell wrapper para chamar seu script, que tenta descobrir onde o nó está e como ele é chamado.
Doon
4
Muitas sugestões nesta resposta no site Unix - unix.stackexchange.com/questions/65235/…
sargant
Eu tenho um script nodejs que mudei de #!/usr/bin/nodepara #!/usr/bin/nodejsquando atualizei do Ubuntu 12.04 para 12.10. E é invocado a partir de um wrapper que verifica os dois. Para uma discussão sobre o #!/usr/bin/envhack, veja esta pergunta e minha resposta .
Keith Thompson
Há uma proposta TC39 no Estágio 3 chamada "Gramática Hashbang" que visa padronizar os hashbangs usados: github.com/tc39/proposal-hashbang
M. Twarog

Respostas:

151

Se o seu script se destina ao uso por desenvolvedores do Node, você deve simplesmente usar

#!/usr/bin/env node

e não se preocupe em tentar a compatibilidade com pessoas que têm apenas o Node instalado como nodejs.

Justificativa:

  • É o que as crianças legais estão fazendo, e se você não fizer isso também, você não será legal. Projetos de node principais como jshint , karma , bower e até mesmo npm simplesmente são usados #!/usr/bin/env nodecomo o shebang para seus scripts executáveis.
  • Porque as crianças legais estão fazendo isso, qualquer pessoa que trabalhe com o Node no Ubuntu configurou um /usr/bin/nodecomo um link simbólico para nodejs. Existem instruções muito vistas sobre como fazer isso aqui no Stack Overflow e em toda a web. Existia até o nodejs-legacypacote cujo propósito era criar este link simbólico para você. As pessoas que usam o Node sabem como consertar esse problema no Ubuntu e precisam fazê-lo se quiserem usar praticamente qualquer software já escrito em Node.
  • O problema nem parece mais existir no Ubuntu 14.04; Limpei o Node e executei um apt-get install nodejse ele foi criado /usr/bin/nodecomo um link simbólico para /etc/alternatives/node. As pessoas afetadas por esse problema são, eu suspeito, uma minoria cada vez menor.

Mesmo que você tenha como alvo pessoas analfabetas do Node, você ainda pode querer usar #!/usr/bin/env node, talvez adicionando a possível necessidade de criação de link simbólico manual ou instalação do nodejs-legacypacote à sua documentação de instalação se você julgar necessário. Observe que se alguém com, nodejsmas não nodedisponível, tentar executar seu programa com o esquema acima, verá:

/ usr / bin / env: node: Não existe esse arquivo ou diretório

e Googling que lhes dará a correção no primeiro resultado e muitas vezes na primeira página.

Se você realmente deseja desesperadamente ter certeza de que o usuário pode executar seu software em um sistema onde nodejsestá disponível, mas nodenão está (ou onde nodeestá realmente o programa Amateur Packet Radio Node ), então você pode usar este "shebang de duas linhas" do Unix e Linux Stack Exchange :

#!/bin/sh
':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@"

console.log('Hello world!');

mas você realmente precisa fazer isso quando quase ninguém mais no mundo Node precisa?

Mark Amery
fonte
2
Se o suporte para o nodejsexecutável for preferido, você pode achar um pouco mais bonito usar um shebang com #!/bin/she //bin/false || exec "$(command -v nodejs || command -v node)" "$0".
lennartcl
2
Observe que você não pode passar argumentos para o nó no Linux , como --experimental-modules, se você usar esta envlinha shebang. Existem hacks por aí, mas eles são feios .
Dan Dascalescu