Como faço para depurar “Error: spawn ENOENT” em node.js?

Quando recebo o seguinte erro:

events.js:72 throw er; // Unhandled 'error' event ^ Error: spawn ENOENT at errnoException (child_process.js:1000:11) at Process.ChildProcess._handle.onexit (child_process.js:791:34) 

Que procedimento posso seguir para corrigi-lo?

Nota do autor : Muitos problemas com esse erro me incentivaram a postar essa pergunta para futuras referências.

Perguntas relacionadas:

  • usando a function spawn com NODE_ENV = produção
  • node.js child_process.spawn Erro ENOENT – somente sob supervisão
  • spawn ENOENT node.js erro
  • https://stackoverflow.com/questions/27603713/nodejs-spawn-enoent-error-on-travis-calling-global-npm-package
  • Node JS – spawn child_process (‘npm install’) na tarefa Grunt resulta em erro ENOENT
  • Tarefa “foreman” em execução Erro fatal: spawn ENOENT
  • evento de erro não manipulado no nó js Erro: desova ENOENT em errnoException (child_process.js: 975: 11)
  • Node.js SpookyJS: erro ao executar o hello.js
  • https://stackoverflow.com/questions/26572214/run-grunt-on-a-directory-nodewebkit
  • Execute o arquivo exe com o Child Process NodeJS
  • Nó: child_process.spawn não está funcionando em Java, embora esteja no caminho (ENOENT)
  • gerar erro ENOENT com NodeJS (relacionado a PYTHON)
  • O redimensionamento de imagem não está funcionando em node.js (partial.js) (dependência não instalada)
  • npm install error ENOENT (problema de dependência de compilation)
  • Não é possível instalar o node.js – módulo oracle no Windows 7 (problema de dependência de compilation)
  • Erro ao instalar o gulp usando o nodejs nas janelas (caso estranho)

Eu encontrei uma maneira fácil de entender a causa raiz de:

 Error: spawn ENOENT 

O problema deste erro é que há realmente poucas informações na mensagem de erro para dizer onde o site de chamada é, ou seja, qual executável / comando não foi encontrado, especialmente quando você tem uma grande base de código onde há muitas chamadas de spawn. . Por outro lado, se soubermos o comando exato que causa o erro, podemos seguir a resposta do @laconbass para corrigir o problema.

Eu encontrei uma maneira muito fácil de identificar qual comando causa o problema, em vez de adicionar listeners de events em todo o seu código, como sugerido na resposta do @laconbass ‘. A idéia-chave é envolver a chamada de desova original com um wrapper que imprime os argumentos enviados para a chamada de desova.

Aqui está a function de wrapper, coloque-a no topo do index.js ou qualquer script inicial do seu servidor.

 (function() { var childProcess = require("child_process"); var oldSpawn = childProcess.spawn; function mySpawn() { console.log('spawn called'); console.log(arguments); var result = oldSpawn.apply(this, arguments); return result; } childProcess.spawn = mySpawn; })(); 

Então, da próxima vez que você executar o seu aplicativo, antes da mensagem da exceção não detectada, você verá algo assim:

 spawn called { '0': 'hg', '1': [], '2': { cwd: '/* omitted */', env: { IP: '0.0.0.0' }, args: [] } } 

Desta forma, você pode facilmente saber qual comando é realmente executado e, em seguida, você pode descobrir por que os nodejs não podem encontrar o executável para corrigir o problema.

Passo 1: Assegure-se de que o spawn é chamado o caminho certo

Primeiro, revise os documentos para child_process.spawn (command, args, options) :

Inicia um novo processo com o command especificado, com argumentos de linha de comando em argumentos. Se omitido, o args assume como padrão um Array vazio.

O terceiro argumento é usado para especificar opções adicionais, cujo padrão é:

{ cwd: undefined, env: process.env }

Use env para especificar variables ​​de ambiente que serão visíveis para o novo processo, o padrão é process.env .

Verifique se você não está colocando nenhum argumento de linha de command no command e se toda a chamada de spawn é válida . Prossiga para o próximo passo.

Etapa 2: Identifique o Emissor de Eventos que emite o evento de erro

Pesquise em seu código-fonte para cada chamada para spawn , ou child_process.spawn , ou seja,

 spawn('some-command', [ '--help' ]); 

e append um ouvinte de evento para o evento ‘error’, assim você será notado o Emissor de Eventos exato que está lançando-o como ‘Unhandled’. Após a debugging, esse manipulador pode ser removido.

 spawn('some-command', [ '--help' ]) .on('error', function( err ){ throw err }) ; 

Execute e você deve obter o caminho do arquivo e o número da linha onde seu listener de ‘erros’ foi registrado. Algo como:

 /file/that/registers/the/error/listener.js:29 throw err; ^ Error: spawn ENOENT at errnoException (child_process.js:1000:11) at Process.ChildProcess._handle.onexit (child_process.js:791:34) 

Se as duas primeiras linhas ainda estiverem

 events.js:72 throw er; // Unhandled 'error' event 

faça este passo novamente até que eles não estejam. Você deve identificar o ouvinte que emite o erro antes de ir para o próximo passo.

Etapa 3: verifique se a variável de ambiente $PATH está definida

Existem dois cenários possíveis:

  1. Você depende do comportamento de spawn padrão, portanto, o ambiente de processo filho será o mesmo que process.env .
  2. Você está passando explicitamente um object env para spawn o argumento de options .

Em ambos os cenários, você deve inspecionar a chave PATH no object de ambiente que o processo filho gerado usará.

Exemplo para o cenário 1

 // inspect the PATH key on process.env console.log( process.env.PATH ); spawn('some-command', ['--help']); 

Exemplo para o cenário 2

 var env = getEnvKeyValuePairsSomeHow(); // inspect the PATH key on the env object console.log( env.PATH ); spawn('some-command', ['--help'], { env: env }); 

A ausência de PATH (ou seja, é undefined ) fará com que o spawn emita o erro ENOENT , já que não será possível localizar nenhum command menos que seja um caminho absoluto para o arquivo executável.

Quando o PATH estiver configurado corretamente, prossiga para o próximo passo. Deve ser um diretório ou uma lista de diretórios. Último caso é o habitual.

Etapa 4: Assegure-se de que o command exista em um diretório daqueles definidos no PATH

O Spawn pode emitir o erro ENOENT se o command filename (ex. ‘Algum comando’) não existir em pelo menos um dos diretórios definidos no PATH .

Localize o local exato do command . Na maioria das distribuições de Linux, isso pode ser feito a partir de um terminal com o comando which . Ele irá dizer-lhe o caminho absoluto para o arquivo executável (como acima), ou dizer se ele não foi encontrado.

Exemplo de uso de qual e sua saída quando um comando é encontrado

 > which some-command some-command is /usr/bin/some-command 

Exemplo de uso de qual e sua saída quando um comando não é encontrado

 > which some-command bash: type: some-command: not found 

Os programas instalados incorretamente são a causa mais comum de um comando não encontrado . Consulte a documentação de cada comando, se necessário, e instale-a.

Quando o comando é um arquivo de script simples, certifique-se de que ele esteja acessível em um diretório no PATH . Se não for, mova-o para um ou crie um link para ele.

Depois que você determinar que o PATH está configurado corretamente e o command está acessível a partir dele, será possível gerar o processo filho sem spawn ENOENT .

Como @DanielImfeld apontou , ENOENT será lançado se você especificar “cwd” nas opções, mas o diretório fornecido não existe.

Solução do Windows: Substitua o spawn por node-cross-spawn . Por exemplo, assim no início do seu app.js:

 (function() { var childProcess = require("child_process"); childProcess.spawn = require('cross-spawn'); })(); 

Para qualquer um que possa se deparar com isso, se todas as outras respostas não ajudarem e você estiver no Windows, saiba que há atualmente um grande problema com o spawn no Windows e a variável de ambiente PATHEXT que pode fazer com que determinadas chamadas não funcionem dependendo sobre como o comando de destino está instalado.

A resposta de @ laconbass me ajudou e provavelmente está mais correta.

Eu vim aqui porque estava usando o spawn incorretamente. Como um exemplo simples:

isso está incorreto:

 const s = cp.spawn('npm install -D suman', [], { cwd: root }); 

isso está incorreto:

 const s = cp.spawn('npm', ['install -D suman'], { cwd: root }); 

isto está certo:

 const s = cp.spawn('npm', ['install','-D','suman'], { cwd: root }); 

no entanto, eu recomendo fazê-lo desta maneira:

 const s = cp.spawn('bash'); s.stdin.end(`cd "${root}" && npm install -D suman`); s.once('exit', code => { // exit }); 

isto é porque então o cp.on('exit', fn) será sempre triggersdo, contanto que o bash seja instalado, caso contrário, o cp.on('error', fn) pode ser cp.on('error', fn) primeiro, se usarmos o primeira maneira, se lançarmos ‘npm’ diretamente.

Para ENOENT no Windows, https://github.com/nodejs/node-v0.x-archive/issues/2318#issuecomment-249355505 corrija-o.

Por exemplo, substitua spawn (‘npm’, [‘-v’], {stdio: ‘inherit’}) por:

  • para toda a versão do node.js:

     spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['-v'], {stdio: 'inherit'}) 
  • para node.js 5.xe posterior:

     spawn('npm', ['-v'], {stdio: 'inherit', shell: true}) 

No meu caso, eu estava recebendo este erro devido ao fato de os resources dependentes do sistema não estarem sendo instalados.

Mais especificamente, eu tenho um aplicativo NodeJS que está utilizando o ImageMagick. Apesar de ter o pacote npm instalado, o núcleo do Linux ImageMagick não foi instalado. Eu fiz um apt-get para instalar o ImageMagick e depois disso tudo funcionou muito bem!

Eu me deparei com o mesmo problema, mas encontrei uma maneira simples de consertar isso. Parece haver erros de spawn() se o programa tiver sido adicionado ao PATH pelo usuário (por exemplo, os comandos normais do sistema funcionam).

Para corrigir isso, você pode usar o módulo npm install --save which ( npm install --save which ):

 // Require which and child_process const which = require('which'); const spawn = require('child_process').spawn; // Find npm in PATH const npm = which.sync('npm'); // Execute const noErrorSpawn = spawn(npm, ['install']); 

Assegure-se de que o módulo a ser executado esteja instalado ou o caminho completo para o comando, se não for um módulo do nó

Use require('child_process').exec vez de spawn para uma mensagem de erro mais específica!

por exemplo:

 var exec = require('child_process').exec; var commandStr = 'java -jar something.jar'; exec(commandStr, function(error, stdout, stderr) { if(error || stderr) console.log(error || stderr); else console.log(stdout); }); 

Eu estava recebendo este erro ao tentar depurar um programa node.js de dentro do editor VS Code em um sistema Debian Linux. Eu notei que a mesma coisa funcionou bem no Windows. As soluções anteriormente dadas aqui não ajudaram muito porque eu não tinha escrito nenhum comando “spawn”. O código ofensivo foi presumivelmente escrito pela Microsoft e escondido sob o capô do programa VS Code.

Em seguida, notei que node.js é chamado node no Windows, mas no Debian (e presumivelmente em sistemas baseados no Debian, como o Ubuntu) é chamado de nodejs. Então eu criei um alias – de um terminal raiz, eu corri

ln -s / usr / bin / nodejs / usr / local / bin / nó

e isso resolveu o problema. O mesmo procedimento ou um procedimento semelhante presumivelmente funcionará em outros casos em que seu node.js é chamado de nodejs, mas você está executando um programa que espera que ele seja chamado de node ou vice-versa.

Eu tenho o mesmo erro para o Windows 8. O problema é porque de uma variável de ambiente do seu caminho do sistema está faltando. Adicione o valor “C: \ Windows \ System32 \” à variável PATH do seu sistema.

Se você estiver no Windows, o Node.js faz algum negócio engraçado ao manipular cotações que podem resultar na emissão de um comando que você sabe que funciona no console, mas não quando executado no Node. Por exemplo, o seguinte deve funcionar:

 spawn('ping', ['"8.8.8.8"'], {}); 

mas falha. Há uma opção fantasticamente não documentada windowsVerbatimArguments para manipular cotações / similar que parece fazer o truque, apenas certifique-se de adicionar o seguinte ao seu object opts:

 const opts = { windowsVerbatimArguments: true }; 

e seu comando deve estar de volta aos negócios.

  spawn('ping', ['"8.8.8.8"'], { windowsVerbatimArguments: true }); 

Eu também estava passando por esse problema irritante durante a execução de meus casos de teste, então tentei muitas maneiras de passar por isso. Mas o caminho funciona para mim é executar o seu executor de teste do diretório que contém seu arquivo principal, que inclui sua function de desova de nodejs algo como isto:

 nodeProcess = spawn('node',params, {cwd: '../../node/', detached: true }); 

Por exemplo, esse nome de arquivo é test.js , portanto, basta mover para a pasta que o contém . No meu caso, é pasta de teste assim:

 cd root/test/ 

em seguida, execute o seu executor de teste no meu caso, o seu mocha por isso vai ser assim:

 mocha test.js 

Eu desperdicei mais de um dia para descobrir. Apreciar!!

Adicione C:\Windows\System32\ à variável de ambiente do path .

Passos

  1. Vá para o meu computador e propriedades

  2. Clique em Configurações avançadas

  3. Então em variables ​​de ambiente

  4. Selecione Path e clique em editar

  5. Cole o seguinte, se ainda não estiver presente: C:\Windows\System32\

  6. Feche o prompt de comando

  7. Execute o comando que você queria executar

Captura de tela do Windows 8 Environment variables