O Node.js é muito popular hoje em dia e eu escrevi alguns scripts nele. Infelizmente, a compatibilidade é um problema. Oficialmente, o intérprete Node.js. deve ser chamado node
, mas o Debian e o Ubuntu enviam um executável chamado nodejs
.
Eu quero scripts portáteis com os quais o Node.js possa trabalhar em tantas situações quanto possível. Supondo que o nome do arquivo seja foo.js
, eu realmente quero que o script seja executado de duas maneiras:
./foo.js
executa o script, se quernode
ounodejs
está em$PATH
.node foo.js
também executa o script (assumindo que o intérprete é chamadonode
)
Nota: As respostas de xavierm02 e de mim são duas variações de um script poliglota. Ainda estou interessado em uma solução pura, se houver.
scripting
compatibility
node.js
dancek
fonte
fonte
node
para o seu script ou ter um tipo de script make que modifique o shebang.alphacentauri
e tal. Se houver um executável chamadonodejs
, você pode ter 99% de certeza de que é Node.js. Por que não apoiar os doisnodejs
enode
?Respostas:
O melhor que eu criei é esse "shebang de duas linhas" que realmente é um script poliglota (Bourne shell / Node.js):
A primeira linha é, obviamente, uma bainha de casca de Bourne. O Node.js ignora qualquer shebang encontrado, portanto, este é um arquivo javascript válido no que diz respeito ao Node.js.
A segunda linha chama o shell no-op
:
com o argumento//
e, em seguida, executanodejs
ounode
com o nome desse arquivo como parâmetro.command -v
é usado em vez dewhich
portabilidade. A sintaxe da substituição de comando$(...)
não é estritamente Bourne; portanto, opte por backticks se você executar isso na década de 1980.O Node.js apenas avalia a string
':'
, que é como um no-op, e o restante da linha é analisado como um comentário.O restante do arquivo é apenas javascript antigo. O subshell é encerrado após a conclusão da
exec
segunda linha, portanto o restante do arquivo nunca é lido pelo shell.Obrigado a xavierm02 pela inspiração e a todos os comentaristas por informações adicionais!
fonte
':'
abordagem é usar// 2>/dev/null
(que é o quenvm
faz): bash, é um erro (bash: //: Is a directory
), que o redirecionamento2>/dev/null
ignora silenciosamente; para JavaScript, a linha inteira se torna um comentário. Além disso - e não espero que isso seja um problema, o IRL -command
possui uma peculiaridade em que também relata funções e aliases de shell com-v
- mesmo que não os invoque. Portanto, se você exportou funções de shell ou até mesmo pseudônimos (supondoshopt -s expand_aliases
) nomeadosnode
ounodejs
, as coisas podem quebrar.mksh
,bash
,dash
e outras conchas em sistemas Unix e GNU modernos.#!/usr/bin/env sh
vez de#!/bin/sh
(por en.wikipedia.org/wiki/Shebang_%28Unix%29#Portability )#!/usr/bin/env sh
como "mais portátil". O mesmo artigo da Wikipedia diz: "Isso funciona principalmente porque o caminho / usr / bin / env é comumente usado para o utilitário env ..." Isso não é um endosso maravilhoso, e meu palpite é que você encontrará sistemas sem/usr/bin/env
mais frequência do que você encontra sistemas sem/bin/sh
, se houver alguma diferença de frequência.//bin/sh -c :; exec ...
uma versão mais limpa da segunda linha?//bin/false
é a mesma coisa que/bin/false
exceto que a segunda barra a transforma em um comentário para o nó, e é por isso que está aqui. Então, o lado direito do primeiro||
é avaliado.'which node || which nodejs'
com aspas em vez de aspas lança o nó e o<<
alimenta o que estiver à direita. Eu poderia ter usado um delimitador começando com o//
dancek, ele teria funcionado, mas acho mais limpo ter apenas duas linhas no começo, então eu costumavatail -n +2 $0
ter o arquivo lido sozinho, exceto as duas primeiras.E se você executá-lo no nó, a primeira linha é reconhecida como um shebang e ignorada e a segunda é um comentário de uma linha.
(Aparentemente, o sed pode ser usado para substituir o conteúdo do arquivo de impressão de cauda sem a primeira e a última linha )
Resposta antes da edição:
Você não pode fazer o que deseja, então o que você faz é executar um script de shell, daí o
#!/bin/sh
. Esse script de shell obterá o caminho do arquivo necessário para executar o nó, ou sejawhich node || which nodejs
. As aspas estão aqui para que sejam executadas, então'which node || which nodejs'
(com as aspas em vez das aspas) simplesmente chama o nó. Então, você apenas alimenta seu script com ele<<
. O__HERE__
são os delimitadores de seu script. E esteconsole.log('ok');
é um exemplo de script que você deve substituir pelo seu script.fonte
<<'__HERE__'
.//bin/false
não funcione no meu ambiente MSYS, e preciso de aspas nos bastidores, pois minhanode
residência está emC:\Program Files\...
. Sim, eu trabalho em um ambiente horrível ...//bin/false
também não funciona no Mac OS X. Sinto muito, mas isso não parece mais muito portátil.which
comando também não é portátil.Este é apenas um problema nos sistemas baseados no Debian, onde a política superou o senso.
Não sei quando o Fedora forneceu um binário chamado nodejs, mas nunca o vi. O pacote é chamado nodejs e instala um nó chamado binário.
Basta usar um link simbólico para aplicar o bom senso aos seus sistemas baseados no Debian e, em seguida, você pode usar um shebang sensato. Outras pessoas estarão usando shebangs sãos de qualquer maneira, então você precisará desse link simbólico.
fonte
nodejs
executável , mas isso não é culpa do Fedora. Desculpe por deturpar o fato.#!/usr/bin/perl
. Dito isto, você não é obrigado a gostar ou aplicar minhas sugestões. Paz.Se você não se importa em criar um pequeno
.sh
arquivo, tenho uma pequena solução para você. Você pode criar um pequeno script de shell para determinar qual nó executável usar e usar esse script em seu shebang:shebang.sh :
script.js :
Marque ambos executáveis e execute
./script.js
.Dessa forma, você evita scripts poliglotas. Não acho que seja possível usar várias linhas shebang, embora pareça uma boa ideia.
Embora isso resolva o problema da maneira que você deseja, parece que ninguém se importa com isso. Por exemplo, uglifyjs e coffeescript usam
#!/usr/bin/env node
, npm usa um script de shell como ponto de entrada, que novamente chama o executável explicitamente com o nomenode
. Sou usuário do Ubuntu e não sabia disso, pois sempre compilo o nó. Estou pensando em relatar isso como um bug.fonte
chmod +x
no script sh ... então você também pode pedir que ele defina uma variável que dê a localização do executável de seu nó ...chmod +x
'd. E eu concordo que uma variável NODE é melhor quewhich node || which nodejs
. Mas o pesquisador deseja fornecer uma experiência pronta para uso, embora muitos projetos importantes de nós apenas o usem#!/usr/bin/env node
.Apenas para completar, aqui estão algumas outras maneiras de fazer a segunda linha:
Mas nenhum dos dois tem vantagem sobre a resposta selecionada:
Além disso, se você soubesse que um
node
ounodejs
(mas não ambos) seria encontrado, o seguinte funciona:Mas esse é um grande "se", então acho que a resposta selecionada continua sendo a melhor.
fonte
foobar // 2>/dev/null
desde quefoobar
não seja um comando. E muitos dos utilitários encontrados em qualquer sistema POSIX podem ser executados com o//
argumentoEntendo que isso não responde à pergunta, mas estou convencido de que a pergunta é feita com uma premissa falsa.
O Ubuntu está errado aqui. Escrever um shebang universal para seu próprio script não mudará outros pacotes dos quais você não tem controle sobre os quais usam o padrão de fato
#!/usr/bin/env node
. Seu sistema deve fornecernode
emPATH
se deseja para todos os scripts visando nodejs para rodar nele.Por exemplo, nem o
npm
pacote fornecido pelo Ubuntu reescreve shebangs nos pacotes:fonte