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 foocujo 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 $PATHpara 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 nodecomando não estiver instalado em /usr/bin.
Uma solução alternativa comum é usar o envcomando (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 envcomando 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 envpesquisar $PATHo comando. Portanto, se nodeestiver instalado /usr/local/bin/nodee você tiver /usr/local/binno seu $PATH, o envcomando será invocado /usr/local/bin/node foo.
O objetivo principal do envcomando é 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/envsim, mas trabalhei em sistemas mais antigos, onde o envcomando 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 nodecomando 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 nodepróprio comando, atualizando o script conforme necessário para diferentes sistemas; ou
- Invoque o
nodecomando com seu script como um argumento.
Veja também esta pergunta (e minha resposta ) para mais discussão sobre o #!/usr/bin/envtruque.
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/nodeque /usr/bin/nodejsentre Ubuntu 12.04 e 12.10. O #!/usr/bin/envtruque 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 nodejse 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 nodejsvs. nodetenha sido resolvido nos anos desde que publiquei esta resposta pela primeira vez. No Ubuntu 18.04, o nodejspacote é instalado /usr/bin/nodejscomo 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-legacypacote fornecido nodecomo um link simbólico para nodejs. Nenhuma garantia de que tenha todos os detalhes corretos.
node