node.js에서“Error : spawn ENOENT”를 어떻게 디버깅합니까?


350

다음과 같은 오류가 발생하면

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)

이를 해결하기 위해 어떤 절차를 따를 수 있습니까?

Author note :이 오류와 관련된 많은 문제로 인해 향후 참조를 위해이 질문을 게시 할 수있었습니다.

관련 질문 :


필자의 경우, exec첫 번째 인수로 명령을 전달하고 두 번째 인수에 대한 옵션을 옵션으로 배열하는 대신 전체 명령을 문자열 로 전달했습니다. 예를 들어 내가 spawn( "adb logcat -c" )대신 하고 있었다 spawn( "adb", [ "logcat", "-c" ] ).
Joshua Pinter

답변:


235

참고 :이 오류는 명령이 존재하지 않거나 작업 디렉토리가 없거나 Windows 전용 버그로 인해 거의 항상 발생합니다.

나는 근본 원인에 대한 아이디어를 얻는 쉬운 방법을 찾았습니다.

Error: spawn ENOENT

이 오류의 문제는 오류 메시지에 콜 사이트의 위치, 즉 어떤 실행 / 명령을 찾을 수 없는지를 알려주는 정보가 거의 없다는 것입니다. 특히 스폰 호출이 많은 대규모 코드 기반이있는 경우 . 반면에 오류를 일으키는 정확한 명령을 알고 있으면 @laconbass의 답변 을 따라 문제를 해결할 수 있습니다.

@laconbass의 답변에서 제안한 것처럼 코드의 모든 곳에 이벤트 리스너를 추가하는 대신 어떤 명령으로 문제를 일으키는 지 쉽게 알 수 있습니다. 핵심 아이디어는 원래 스폰 호출을 래퍼로 래핑하여 인수 전송을 스폰 호출로 인쇄하는 것입니다.

다음은 랩퍼 기능 index.js입니다. 서버 시작 스크립트의 맨 위에 놓으십시오 .

(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;
})();

다음에 응용 프로그램을 실행할 때 발견되지 않은 예외 메시지가 표시되기 전에 다음과 같은 내용이 표시됩니다.

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

이런 식으로 실제로 어떤 명령이 실행되는지 쉽게 알 수 있으며 nodejs가 문제를 해결하기 위해 실행 파일을 찾을 수없는 이유를 찾을 수 있습니다.


3
여기에 또 다른 생각 : 단지 변경 spawn()exec()하고 다시 시도하십시오. exec()어떤 명령 을 실행 하려고 했는지 알려줍니다 .
Adam Monsen

1
중요 사항 : 위 코드를 가능한 한 기본 JS 파일의 시작 부분에 가깝게 배치하십시오. 다른 모듈을 먼저로드하면 'spawn'기능을 숨길 수 있으며 여기서 재정의는 호출되지 않습니다.
Dan Nissenbaum 2016 년

1
스크립트를 사용하여 운이 없습니다. 전혀 작동하지 않습니다.
newguy

그렇다면이 방법을 그런트 파일에서 어떻게 사용 하시겠습니까? 어디에 넣을지 잘 모르겠습니다.
Felix Eve

2
이것은 나를 위해 완벽하게 작동했습니다. 방금 gulpfile.js 파일의 상단과 빙고 방고 봉고에 스폰 로깅을 넣었습니다!
Yann Duran

121

1 단계 : spawn올바른 방법으로 확인

먼저 child_process.spawn (command, args, options) 문서를 검토하십시오 .

주어진 command명령 줄 인수와 함께 새로운 프로세스를 시작합니다 args. 생략하면 args기본값은 빈 배열입니다.

세 번째 인수는 추가 옵션을 지정하는 데 사용되며 기본값은 다음과 같습니다.

{ cwd: undefined, env: process.env }

사용하여 env새로운 프로세스로 볼 수 있습니다 환경 변수를 지정하려면 기본입니다 process.env.

명령 행 인수를 넣지 않았고 command전체 spawn호출이 유효한지 확인하십시오 . 다음 단계로 진행하십시오.

2 단계 : 오류 이벤트를 발생시키는 이벤트 이미 터 식별

각 호출에 대한 소스 코드를에 검색 spawn하거나 child_process.spawn, 즉,

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

거기에 'error'이벤트에 대한 이벤트 리스너를 연결하면 'Unhandled'로 던지는 정확한 이벤트 이미 터가 나타납니다. 디버깅 후 해당 핸들러를 제거 할 수 있습니다.

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

실행하면 '오류'리스너가 등록 된 파일 경로와 줄 번호를 가져와야합니다. 다음과 같은 것 :

/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)

처음 두 줄이 여전히

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

그렇지 않을 때까지이 단계를 다시 수행하십시오. 다음 단계로 진행하기 전에 오류를 발생시키는 리스너를 식별해야합니다.

3 단계 : 환경 변수 $PATH가 설정되어 있는지 확인

두 가지 가능한 시나리오가 있습니다.

  1. 기본 spawn동작 에 의존 하므로 하위 프로세스 환경은와 동일합니다 process.env.
  2. 인수 에 env객체를 명시 적으로 전달하고 있습니다.spawnoptions

두 시나리오 모두 PATH에서 생성 된 자식 프로세스가 사용할 환경 개체 의 키를 검사해야합니다 .

시나리오 1의 예

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

시나리오 2의 예

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

의 부재는 PATH(즉, 그것의가 undefined)의 원인이됩니다 spawn방출하는 ENOENT오류 는 어떤 위치를 할 수 없으므로, command이 실행 파일의 절대 경로가 아니면.

PATH설정이 끝나면 다음 단계로 진행하십시오. 디렉토리이거나 디렉토리 목록이어야합니다. 마지막 경우가 일반적입니다.

4 단계 : command에 정의 된 디렉토리에 존재 하는지 확인PATH

ENOENT파일 이름 command(예 : 'some-command')이에 정의 된 디렉토리 중 하나 이상에 없으면 스폰에서 오류가 발생할 수 있습니다 PATH.

의 정확한 위치를 찾으십시오 command. 대부분의 리눅스 배포판에서는이 which명령 을 사용하여 터미널에서이를 수행 할 수 있습니다 . 실행 파일의 절대 경로 (위와 같이)를 찾거나 찾을 수 없는지 알려줍니다.

명령이 발견 될 때의 사용법 및 출력 예

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

명령을 찾을 수없는 경우의 사용법 및 출력 예

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

잘못 설치된 프로그램은 찾을 수없는 명령 의 가장 일반적인 원인입니다 . 필요한 경우 각 명령 설명서를 참조하여 설치하십시오.

command가 간단한 스크립트 파일 인 경우의 디렉토리에서 액세스 할 수 있는지 확인하십시오 PATH. 그렇지 않은 경우 다른 것으로 이동하거나 링크를 만드십시오.

PATH올바르게 설정되어 command액세스 가능한 것으로 판단되면 , 자식 프로세스를 spawn ENOENT던지지 않고 생성 할 수 있어야합니다 .


1
이것은 Spawn ENOENT의 디버깅에 매우 도움이되었습니다. 나는 그것을 여러 번 참조했다. 감사!
CodeManiak

36
또한 cwd옵션에 지정하면 ENOENT가 발생 하지만 주어진 디렉토리가 존재하지 않는 것으로 나타났습니다 .
Daniel Imfeld

4
@DanielImfeld TOTAL SAVIOUR. 이것을 말하는 답을 써야합니다.
GreenAsJade

4
spawn('some-command', ['--help'], { env: env });이 답변의 3 단계에 설명 된대로 사용 하고 사용자 정의 환경을 전달하는 경우을 지정하십시오 ( PATH예 :) { env: { PATH: process.env.PATH } }. env 옵션은 기본적으로 현재 env의 변수를 상속하지 않습니다.
anty

5
shell: true스폰 옵션 으로 전달 하여 문제를 해결할 수있었습니다 .
Nickofthyme

35

으로 @DanielImfeld이 그것을 지적 , 당신은 옵션에서 "CWD"를 지정하면 ENOENT가 발생되지만, 주어진 디렉토리가 존재하지 않습니다.


1
특정 디렉토리에서 명령을 실행하는 방법이 있습니까?
Mitro

윈도우에서 (7) 당신은 또한에 드라이브 문자를 포함 할 필요가 보인다 cwd경로 : 'C를 : / ...'뿐 아니라 '/ ...'
Museful

29

윈도우 솔루션 : 교체 spawn노드 간 산란 . 예를 들어 app.js의 시작 부분에서 다음과 같이하십시오.

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

2
드롭 인 인 경우를 제외하고는 child_process가 필요하지 않습니다. 정확히 노드의 스폰이나 스폰 싱크와 같은 방식이므로 대체품이 떨어집니다. var spawn = require('cross-spawn'); // Spawn NPM asynchronously var child = spawn('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' });
Bogdan Trusca

27

@laconbass의 답변이 도움이되었으며 아마도 가장 정확할 것입니다.

스폰을 잘못 사용했기 때문에 여기에 왔습니다. 간단한 예로서 :

이것은 올바르지 않습니다 :

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

이것은 올바르지 않습니다 :

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

이것은 맞습니다 :

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

그러나 다음과 같이하는 것이 좋습니다.

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

cp.on('exit', fn)bash가 설치되어 있는 한 이벤트가 항상 시작 되기 때문입니다 . 그렇지 않으면 cp.on('error', fn)'npm'을 직접 시작하면 첫 번째 방법으로 이벤트를 사용 하면 이벤트가 먼저 시작될 수 있습니다.


1
"일반적인 가이드"를 제공하기 위해 내 대답을 리팩토링하고 문제의 각 원인에 대한 세부 정보를 남겨 둡니다 (결석 종속성, 잘못된 전화, 잘못된 환경 등).
laconbass

2
이 답변을 좋아하는 사람은,이 기본 대안에 관심이있을 수 있습니다 : gist.github.com/ORESoftware/7bf225f0045b4649de6848f1ea5def4c
알렉산더 밀스를

1
당신이 갖고 싶어하는 것은 쉘의 경우 다음 사용해야하기 때문에을 downvoted child_process.exec또는 통과 shell: truespawn.
givanse

@givanse 반드시 사실이 아니다 - 당신은 당신이 사용하고자하는 쉘을에 따라 zsh을 또는 bash는 또는 난포 자극 호르몬 (FSH)을 실행할 수 있으며, 동작도 다릅니다
알렉산더 밀스

22

Windows의 ENOENT의 경우 https://github.com/nodejs/node-v0.x-archive/issues/2318#issuecomment-249355505로 수정하십시오.

예를 들어 spawn ( 'npm', [ '-v'], {stdio : 'inherit'})을 다음과 같이 바꾸십시오.

  • 모든 node.js 버전의 경우 :

    spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['-v'], {stdio: 'inherit'})
  • node.js 5.x 이상의 경우 :

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

1
이러한 수정 작업은 어디에서해야합니까?
Deilan

8
핵심 부분은 다음과 같습니다shell: true
Ted Nyberg

19

이 문제에 걸려 넘어 질 수있는 사람이라면, 다른 모든 답변이 도움이되지 않고 Windows를 사용하는 경우 현재 Windows 및 환경 변수 큰 문제가spawnPATHEXT 있으며 방법에 따라 특정 호출이 발생하지 않을 수 있음을 알고 있습니다. 대상 명령이 설치되었습니다.


2
그리고 해결책은 무엇입니까?
Nilzor

6
node-cross-spawn을 사용하면 나를 위해 일했습니다. 아래 답변을 참조하십시오 : stackoverflow.com/a/35561971/507339
Nilzor

1
오랜 세월 동안 무엇이 잘못되었는지 알아 내려고 노력하면서 결국 문제가되었습니다. 나는 포기하고 대신에 spawn사용 exec했다.
재개 됨

8

필자의 경우 필요한 종속 시스템 리소스가 설치되지 않아서이 오류가 발생했습니다.

더 구체적으로, ImageMagick을 사용하는 NodeJS 앱이 있습니다. npm 패키지가 설치되었지만 핵심 Linux ImageMagick은 설치되지 않았습니다. 나는 ImageMagick을 설치하기 위해 apt-get을했고 그 후 모두 훌륭하게 작동했습니다!


윈도우에 ImageMagick도 설치해야합니까? Windows에서 테스트
중이고

6

Windows에서 shell: true옵션을 추가 하면 내 문제가 해결되었습니다.

틀렸다 :

const { spawn } = require('child_process');
const child = spawn('dir');

옳은:

const { spawn } = require('child_process');
const child = spawn('dir', [], {shell: true});

5

env옵션 을 변경하고 있습니까?

그런 다음이 답변을보십시오.


나는 노드 프로세스와 TIL을 생성하려고 시도했지만 다른 환경을 생성 할 때 기존 환경 변수를 확산시켜야합니다. PATH환경 변수와 다른 중요한 변수를 잃어 버릴 것입니다.

이것은 나를위한 수정이었습니다.

const nodeProcess = spawn('node', ['--help'], {
  env: {
    // by default, spawn uses `process.env` for the value of `env`
    // you can _add_ to this behavior, by spreading `process.env`
    ...process.env,
    OTHER_ENV_VARIABLE: 'test',
  }
});

4

누군가이 문제를 디버깅하는 데 많은 시간을 보내기 전에 대부분의 node_modules경우 패키지를 삭제 하고 다시 설치하여 해결할 수 있습니다 .

설치하기 위해서:

잠금 파일이 존재하면 다음을 사용할 수 있습니다.

yarn install --frozen-lockfile

또는

npm ci

정중하게. 그렇지 않다면

yarn install

또는

npm i

와우 그런 간단한 해결책과 그것은 나를 위해 일했다! 모든 사람이 먼저 문제를 해결하는지 확인해야합니다.
Nick K

2

같은 문제가 발생했지만 문제를 해결하는 간단한 방법을 찾았습니다. 사용자가 spawn()프로그램을 PATH에 추가 한 경우 오류가 발생한 것 같습니다 (예 : 일반 시스템 명령 작동).

이 문제를 해결하기 위해 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']);

2

require('child_process').exec보다 구체적인 오류 메시지를 위해 스폰 대신 사용하십시오 !

예를 들면 다음과 같습니다.

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);
});

1

실행할 모듈이 설치되어 있는지 또는 노드 모듈이 아닌 경우 명령의 전체 경로를 확인하십시오.


1

또한 테스트 사례를 실행하는 동안이 성가신 문제를 겪고 있었으므로 여러 가지 방법으로 시도했습니다. 그러나 나를 위해 작동하는 방법은 다음과 같이 nodejs 생성 기능 을 포함하는 기본 파일들어있는 디렉토리에서 테스트 러너실행하는 것입니다.

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

예를 들어이 파일 이름은 test.js 이므로 파일 이 포함 된 폴더로 이동하십시오 . 필자의 경우 다음과 같은 테스트 폴더입니다.

cd root/test/

그런 다음 내 경우 테스트 러너실행하여 다음 과 같이 모카를 만듭니다.

mocha test.js

나는 그것을 알아 내기 위해 하루 이상을 낭비했다. 즐겨!!


1

Windows 에서이 문제에 부딪 쳤습니다. 호출 execspawn똑같은 명령 (인수 생략 )이 제대로 작동했지만 ( exec내 명령이 켜져 $PATH있음을 알았습니다 ) spawnENOENT를 줄 것입니다. .exe내가 사용하고있는 명령 에 추가해야한다는 것이 밝혀졌습니다 .

import { exec, spawn } from 'child_process';

// This works fine
exec('p4 changes -s submitted');

// This gives the ENOENT error
spawn('p4');

// But this resolves it
spawn('p4.exe');
// Even works with the arguments now
spawn('p4.exe', ['changes', '-s', 'submitted']);

0

데비안 리눅스 시스템의 VS 코드 편집기에서 node.js 프로그램을 디버깅하려고 할 때이 오류가 발생했습니다. Windows에서도 동일한 기능을 수행하는 것으로 나타났습니다. 이전에 여기에 제공된 솔루션은 "spawn"명령을 작성하지 않았기 때문에 별 도움이되지 않았습니다. 문제가되는 코드는 Microsoft에 의해 작성되었을 수 있으며 VS 코드 프로그램 내부에 숨겨져 있습니다.

다음으로 node.js는 Windows에서는 node라고하지만 데비안에서는 (그리고 아마도 Ubuntu와 같은 데비안 기반 시스템에서는) nodejs라고합니다. 그래서 루트 터미널에서 별칭을 만들었습니다.

ln -s / usr / bin / nodejs / usr / local / bin / node

그리고 이것은 문제를 해결했습니다. node.js가 nodejs라고 불리는 다른 경우에도 동일하거나 유사한 절차가 작동하지만 아마도 node라고 부르는 프로그램을 실행 중이거나 그 반대 일 수도 있습니다.


0

Windows Node.js를 사용하는 경우 따옴표를 처리 할 때 재미있는 비즈니스를 수행하여 콘솔에서 작동하지만 노드에서는 실행되지 않는 명령을 발행 할 수 있습니다. 예를 들어 다음 작동합니다.

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

그러나 실패합니다. windowsVerbatimArguments트릭을 수행하는 것처럼 보이는 따옴표 / 유사 항목을 처리 하는 환상적인 문서화 옵션 이 있습니다. opts 객체에 다음을 추가하십시오.

const opts = {
    windowsVerbatimArguments: true
};

그리고 당신의 명령은 사업에 복귀해야합니다.

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

배열 내부의 인수를 인용하지 마십시오
laconbass

@laconbass 이것은 개념을 전달하는 명백한 예이므로 인용 부호를 제거 할 수 있습니다. 그러나 인수를 반드시 인용해야하는 경우가 있습니다 (예 : 공백이있는 경로가있는 인수를 전달해야하는 경우 : "C : \ Program Files \ ..." ). 특정 오류 사례의 원인이 아닐 수도 있지만 여기에서 노드가 Windows에서 따옴표를 처리했기 때문에이 암호 오류를 겪는 다른 사람을 도울 수 있기 때문에 여기에 게시했습니다.
Joel B

node.js는 이미 일부 Black Magic을 만들고 인수를 "적절하게"인용합니다. 예제는 언급되지 않은 옵션없이 배열 내부의 인수를 인용하여 작동합니다.
laconbass

내 경험을 추가하기 위해 노드에서 Java 프로세스를 실행하고있었습니다. 이 오류는 인수가 아닌 명령 주위에 따옴표로 인해 나에게 발생했습니다. 명령 경로에 공백으로 테스트해도 따옴표없이 작동합니다.
Troncoso

0

내 경우의 해결책

var spawn = require('child_process').spawn;

const isWindows = /^win/.test(process.platform); 

spawn(isWindows ? 'twitter-proxy.cmd' : 'twitter-proxy');
spawn(isWindows ? 'http-server.cmd' : 'http-server');

1
이것이 승리 특정 수정에 대한 해결책 일지 모르지만, 나는 그것이 ENOENT
laconbass

왜 그런지 모르겠지만 스폰 호출은 노드없이 repl에서 작동 .cmd하지만 typescript jest 테스트에서는 실패합니다. -이 오류는 파악하기가 매우 어려울 수 있습니다.
Mathieu CAROFF

0

소스를 수정할 수없는 애플리케이션에서이 문제가 발생하는 경우 환경 변수를로 NODE_DEBUG설정하여 호출하는 것을 고려하십시오 ( child_process예 :) NODE_DEBUG=child_process yarn test. 이것은 어떤 디렉토리에서 어떤 명령 행이 호출되었는지에 대한 정보를 제공하며 일반적으로 마지막 세부 사항이 실패 이유입니다.


0

일부 사람들에게는 환경 경로 또는 다른 문제 일 수 있지만 Windows 10에 Visual Studio Code 용 Latex Workshop 확장 프로그램을 설치했으며 PDF를 빌드 / 미리보기하려고 할 때이 오류가 발생했습니다. VS Code를 관리자로 실행하면 문제가 해결되었습니다.


1
다시 말하지만, 파일 시스템 경로와 관련이 있습니다. 확장은 아마도 관리자 권한이없는 경로에 도달 할 수
laconbass

-1

Windows 8에서 동일한 오류가 발생했습니다. 문제는 시스템 경로의 환경 변수가 없기 때문입니다. "C : \ Windows \ System32 \"값을 시스템 PATH 변수에 추가하십시오.


-2

추가 C:\Windows\System32\받는 사람path 환경 변수입니다.

단계

  1. 컴퓨터 및 속성으로 이동

  2. 고급 설정을 클릭하십시오

  3. 그런 다음 환경 변수에

  4. 고르다 Path 하고 편집을 클릭하십시오

  5. 아직없는 경우 다음을 붙여 넣습니다. C:\Windows\System32\

  6. 명령 프롬프트를 닫습니다

  7. 실행하려는 명령을 실행하십시오.

Windows 8 환경 변수 스크린 샷


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.