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)

それを修正するためにどのような手順に従うことができますか?

著者注記:このエラーに関する多くの問題により、今後の参考のためにこの質問を投稿することが奨励されました。

関連する質問:


私の場合、exec最初の引数としてコマンドを渡し、2番目の引数の配列としてオプションを渡すのではなく、コマンド全体を文字列として渡していました。例えば、私はspawn( "adb logcat -c" )代わりにやっていましたspawn( "adb", [ "logcat", "-c" ] )
Joshua Pinter

回答:


235

注:このエラーは、ほとんどの場合、コマンドが存在しないため、作業ディレクトリが存在しないため、またはWindowsのみのバグが原因です。

私は以下の根本的な原因を理解するための簡単な方法を見つけました。

Error: spawn ENOENT

このエラーの問題は、呼び出しサイトがどこにあるか、つまり、実行可能ファイル/コマンドが見つからないことを伝えるためのエラーメッセージの情報がほとんどないことです。 。一方、エラーの原因となっている正確なコマンドがわかっている場合は、@ laconbassの回答をたどることができます問題を修正。

@laconbassの回答で提案されているように、コード内のどこにでもイベントリスナーを追加するのではなく、どのコマンドが問題の原因であるかを特定する非常に簡単な方法を見つけました。重要なアイデアは、spawn呼び出しに送信される引数を出力するラッパーで元のspawn呼び出しをラップすることです。

これはラッパー関数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、2015

1
重要:上記のコードは、メインのJSファイルの先頭のできるだけ近くに配置してください。最初に他のモジュールをロードすると、「spawn」関数を隠してしまう可能性があり、ここでのオーバーライドは呼び出されません。
Dan Nissenbaum 2015年

1
スクリプトを使用しても運がありません。まったく機能しません。
newguy 2016年

では、このメソッドをイサキファイルでどのように使用しますか?これをどこに置くかわかりません。
Felix Eve

2
これは完璧に機能しました。これをgulpfile.jsファイルの一番上に配置し、bingo bango bongoでスポーンロギングを作成します。
Yann Duran

121

ステップ1:確認する spawn正しい方法で呼び出されるする

まず、child_process.spawn(command、args、options)ドキュメントを確認します

commandコマンドライン引数をに指定して、指定されたで新しいプロセスを起動しargsます。省略した場合argsデフォルトで空の配列になります。

3番目の引数は、追加のオプションを指定するために使用されます。デフォルトは次のとおりです。

{ cwd: undefined, env: process.env }

env新しいプロセスに表示される環境変数を指定するために使用しますprocess.env。デフォルトはです。

コマンドライン引数を入力していないことcommandと、spawn呼び出し全体が有効であることを確認してください。次のステップに進みます。

手順2:エラーイベントを発行するイベントエミッターを特定する

spawn、またはの呼び出しごとにソースコードを検索しますchild_process.spawn。つまり、

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

そして、そこに「エラー」イベントのイベントリスナーをアタッチすると、「未処理」としてスローされている正確なイベントエミッターに気付くでしょう。デバッグ後、そのハンドラーを削除できます。

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)

最初の2行がまだ

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

なくなるまでこの手順を繰り返します。次の手順に進む前に、エラーを発生させるリスナーを特定する必要があります。

ステップ3:環境変数を確認する $PATHが設定されている

次の2つのシナリオが考えられます。

  1. デフォルトのspawn動作に依存しているため、子プロセス環境はと同じになりprocess.envます。
  2. 引数にenvオブジェクトを明示的に渡しspawnていoptionsます。

どちらのシナリオで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)とspawnENOENTエラーが発生しcommandます。実行可能ファイルへの絶対パスでない限りエラーを特定することができないためです。

PATHが正しく設定されたら、次の手順に進みます。これは、ディレクトリまたはディレクトリのリストである必要があります。最後のケースは通常です。

手順4:でcommand定義されたディレクトリのディレクトリに存在することを確認しますPATH

で定義されたディレクトリの少なくとも1つにENOENTファイル名command(「some-command」など)が存在しない場合、Spawnはエラーを生成することがありますPATH

の正確な場所を見つけますcommand。ほとんどのLinuxディストリビューションでは、これはwhichコマンドを使用して端末から実行できます。(上記のように)実行可能ファイルへの絶対パスが表示されるか、見つからないかどうかが表示されます。

コマンドが見つかったときのwhichとその出力の使用例

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

コマンドが見つからない場合のwhichとその出力の使用例

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

インストールが失敗したプログラムは、見つからないコマンドの最も一般的な原因です。必要に応じて各コマンドのドキュメントを参照し、インストールしてください。

commandが単純なスクリプトファイルの場合は、上のディレクトリからアクセスできることを確認してくださいPATHそうでない場合は、1つに移動するか、リンクを作成します。

PATHが正しく設定されていcommandてアクセス可能であると判断したら、spawn ENOENTスローせずに子プロセスを生成できるはずです。


1
これは、Spawn ENOENTのデバッグに非常に役立ちました。何度も参照しました。ありがとう!
CodeManiak

36
またcwd、オプションで指定した場合、ENOENTがスローされますが、指定されたディレクトリは存在しません。
Daniel Imfeld

4
@DanielImfeld完全な救世主。これを言う答えを書いてください。
GreenAsJade 2015年

4
spawn('some-command', ['--help'], { env: env });この回答のステップ3で例示されているように使用していて、カスタム環境を渡しているPATH場合は、たとえばを指定してください{ env: { PATH: process.env.PATH } }。envオプションは、デフォルトでは現在のenvから変数を継承しません。
16

5
shell: trueスポーンオプションを渡すことで問題を解決できました。
Nickofthyme

35

@DanielImfeldがそれを指摘し、あなたはオプションで「CWD」を指定した場合、ENOENTがスローされますが、指定されたディレクトリが存在しません。


1
それで、特定のディレクトリでコマンドを実行する方法はありますか?
Mitro

Windows(7)では、cwdパスにドライブ文字も含める必要があるようです。 '/ ...'ではなく 'c:/ ...'
Museful

29

Windowsのソリューション:交換するspawn、ノードのクロス産卵。たとえば、app.jsの冒頭で次のようにします。

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

2
ドロップイン以外は機能し、child_processは必要ありません。ノードのspawnまたはspawnSyncとまったく同じなので、これは代わりのドロップです。var spawn = require('cross-spawn'); // Spawn NPM asynchronously var child = spawn('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' });
Bogdan Trusca

27

@laconbassの答えは私を助け、おそらく最も正しいです。

spawnを間違って使用していたので、ここに来ました。簡単な例として:

これは間違っています:

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
Alexander Mills

1
欲しいのがシェルの場合はを使用するchild_process.execか渡す必要があるため、反対票を投じshell: trueましたspawn
givanse

@givanseは必ずしも当てはまりません。使用するシェルに応じて、zsh、bash、またはfshを実行することもできます。動作も異なります
Alexander Mills

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
これらの変更はどこで行うのですか?
デイラン2017年

8
重要な部分が追加されますshell: true
Ted Nyberg、2013

19

これにつまずく可能性のある人にとって、他のすべての回答が役に立たず、Windowsを使用している場合、Windowsと環境変数に大きな問題spawnがあることを知ってください。PATHEXTターゲットコマンドがインストールされます。


2
そして、解決策は何ですか?
Nilzor

6
node-cross-spawnを使用するとうまくいきました。:以下の答えを参照してくださいstackoverflow.com/a/35561971/507339
Nilzor

1
何が悪いのかを見つけようとする歳月は、これが問題となった。私はあきらめて代わりにspawn使用しexecました。
リダック

8

私の場合、必要な依存システムリソースがインストールされていないため、このエラーがスローされていました。

より具体的には、ImageMagickを利用しているNodeJSアプリがあります。npmパッケージがインストールされているにもかかわらず、コアLinux ImageMagickはインストールされませんでした。ImageMagickをインストールするためにapt-getを実行しましたが、その後はすべてうまくいきました!


WindowsにもImageMagickをインストールする必要がありますか?Windowsでのテストとエラーの発生
Somename

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より具体的なエラーメッセージについては、spawnの代わりに使用してください!

例えば:

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 spawn関数を含むメインファイルを含むディレクトリからテストランナー実行することです。

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

Debian LinuxシステムのVSコードエディター内からnode.jsプログラムをデバッグしようとすると、このエラーが発生しました。同じことがWindowsでも問題なく動作することに気づきました。以前にここで示した解決策は、「spawn」コマンドを何も記述していなかったため、あまり役に立ちませんでした。問題のコードはおそらくMicrosoftによって作成されたものであり、VS Codeプログラムの内部に隠されていました。

次に、node.jsはWindowsではnodeと呼ばれていますが、Debian(およびおそらくUbuntuなどのDebianベースのシステム)ではnode.jsと呼ばれています。エイリアスを作成しました-ルート端末から実行しました

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

これで問題が解決しました。同じまたは同様の手順は、node.jsがnodejsと呼ばれる他の場合に機能すると思われますが、nodeと呼ばれることを期待するプログラムを実行しているか、またはその逆です。


0

Windowsを使用している場合、Node.jsは引用符を処理するときにおかしな処理を行い、コンソールから機能することがわかっているコマンドを発行する可能性がありますが、Nodeで実行した場合はそうではありません。たとえば、以下機能するはずです。

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

しかし失敗します。windowsVerbatimArguments引用符/類似のものを処理するための素晴らしい文書化されていないオプションがあり、トリックを行うように見えますが、optsオブジェクトに以下を追加してください:

const opts = {
    windowsVerbatimArguments: true
};

そして、あなたのコマンドはビジネスに戻っているはずです。

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

配列内の引数を引用しないでください
laconbass 2017年

@laconbassこれはコンセプトを伝えるための明白な例であり、引用符を削除することができます。ただし、引数を絶対に引用する必要がある場合があります(たとえば、スペースを含むパスを持つ引数を渡す必要がある場合:"C:\ Program Files \ ...")。私がここに投稿したのは、特定のエラーケースの原因ではなかったとしても、私が遭遇したようにNodeがWindowsで引用符を処理するため、この不可解なエラーが発生している他の人の助けになると思います。
Joel B

node.jsはすでにいくつかのブラックマジックを作成しており、引数を「適切に」暗黙のうちに引用しています。あなたの例は、あなたが言及した文書化されていないオプションなしで、配列内の引数の引用符を外さずに動作するはずです。
ラコンバス2017

私自身の経験を追加するために、ノードから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
これはwin固有の修正の解決策になるかもしれませんが、ENOENTの実際の原因をデバッグするのにどのように役立つかわかりません
laconbass

理由はわかりませんが、spawn呼び出しはなしでノード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コードを実行すると、問題が解決しました。


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.