Os scripts que devem ser executados por um intérprete normalmente têm uma linha shebang na parte superior para informar ao SO como executá-los.
Se você tiver um script foo
cujo nome é a primeira linha #!/bin/sh
, o sistema lerá essa primeira linha e executará o equivalente de /bin/sh foo
. Por causa disso, a maioria dos intérpretes são configurados para aceitar o nome de um arquivo de script como um argumento de linha de comando.
O nome do intérprete após o #!
deve ser um caminho completo; o sistema operacional não pesquisará o seu $PATH
para encontrar o intérprete.
Se você tiver um script para ser executado node
, a maneira óbvia de escrever a primeira linha é:
#!/usr/bin/node
mas isso não funciona se o node
comando não estiver instalado em /usr/bin
.
Uma solução alternativa comum é usar o env
comando (que não foi realmente projetado para essa finalidade):
#!/usr/bin/env node
Se o seu script for chamado foo
, o sistema operacional fará o equivalente a
/usr/bin/env node foo
O env
comando executa outro comando cujo nome é fornecido em sua linha de comando, passando todos os argumentos a seguir para esse comando. O motivo pelo qual ele é usado aqui é para env
pesquisar $PATH
o comando. Portanto, se node
estiver instalado /usr/local/bin/node
e você tiver /usr/local/bin
no seu $PATH
, o env
comando será invocado /usr/local/bin/node foo
.
O objetivo principal do env
comando é executar outro comando com um ambiente modificado, adicionando ou removendo variáveis de ambiente especificadas antes de executar o comando. Mas sem argumentos adicionais, ele apenas executa o comando com um ambiente inalterado, que é tudo de que você precisa neste caso.
Existem algumas desvantagens nessa abordagem. A maioria dos sistemas modernos do tipo Unix /usr/bin/env
sim, mas trabalhei em sistemas mais antigos, onde o env
comando foi instalado em um diretório diferente. Pode haver limitações em argumentos adicionais que você pode passar usando este mecanismo. Se o usuário não tiver o diretório que contém o node
comando em $PATH
, ou se algum comando diferente for chamado node
, ele poderá invocar o comando errado ou não funcionar.
Outras abordagens são:
- Use uma
#!
linha que especifica o caminho completo para o node
próprio comando, atualizando o script conforme necessário para diferentes sistemas; ou
- Invoque o
node
comando com seu script como um argumento.
Veja também esta pergunta (e minha resposta ) para mais discussão sobre o #!/usr/bin/env
truque.
Aliás, no meu sistema (Linux Mint 17.2), ele está instalado como /usr/bin/nodejs
. De acordo com as minhas anotações, ele mudou de /usr/bin/node
que /usr/bin/nodejs
entre Ubuntu 12.04 e 12.10. O #!/usr/bin/env
truque não ajudará com isso (a menos que você configure um link simbólico ou algo semelhante).
ATUALIZAÇÃO: Um comentário de mtraceur diz (reformatado):
Uma solução alternativa para o problema nodejs vs node é iniciar o arquivo com as seguintes seis linhas:
#!/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
*/
Isso tentará primeiro nodejs
e depois tentará node
, e somente imprimirá as mensagens de erro se ambas não forem encontradas. Uma explicação está fora do escopo desses comentários, estou apenas deixando-a aqui para o caso de ajudar alguém a lidar com o problema, já que esta resposta trouxe o problema à tona.
Não tenho usado o NodeJS recentemente. Minha esperança é que o problema nodejs
vs. node
tenha sido resolvido nos anos desde que publiquei esta resposta pela primeira vez. No Ubuntu 18.04, o nodejs
pacote é instalado /usr/bin/nodejs
como um link simbólico para /usr/bin/node
. Em algum sistema operacional anterior (Ubuntu ou Linux Mint, não tenho certeza de qual), havia um nodejs-legacy
pacote fornecido node
como um link simbólico para nodejs
. Nenhuma garantia de que tenha todos os detalhes corretos.
node