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)
作者注 :このエラーに関する多くの問題により、今後の参考のためにこの質問を投稿することが推奨されました。
関連質問:
私は根本的な原因の考えを得るための特定の簡単な方法を見つけました:
Error: spawn ENOENT
このエラーの問題は、コールサイトがどこにあるのか、つまりどの実行可能ファイル/コマンドが見つからないのかを伝えるためのエラーメッセージの情報がほとんどないことです。 。一方、エラーの原因となる正確なコマンドがわかっていれば、 @laconbass 'answer に従って問題を解決できます。
@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が問題を解決するための実行ファイルを見つけることができない理由を見つけることができます。
spawn
が正しい方法で呼ばれるようにする最初に、child_process.spawn(command、args、options)の ドキュメントを確認してください :
command
にコマンドライン引数を指定して、指定されたargs
で新しいプロセスを起動します。省略した場合、args
はデフォルトで空の配列になります。3番目の引数は追加のオプションを指定するために使用されます。デフォルトは次のとおりです。
{ cwd: undefined, env: process.env }
新しいプロセスに表示される環境変数を指定するには
env
を使用します。デフォルトはprocess.env
です。
command
にコマンドライン引数を指定していないこと、およびspawn
呼び出し全体が有効であることを確認してください 。次のステップに進んでください。
spawn
またはchild_process.spawn
を呼び出すたびに、ソースコードを検索します。
spawn('some-command', [ '--help' ]);
'error'イベント用のイベントリスナをそこにアタッチすると、 'Unhandled'としてそれを投げている正確なEvent Emitterに気付くでしょう。デバッグ後、そのハンドラは削除できます。
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
そうでないまで、このステップをもう一度実行してください。 次の手順に進む前に、エラーを発行したリスナーを特定する必要があります。
$PATH
が設定されていることを確認してください考えられるシナリオは2つあります。
spawn
の振る舞いに頼るので、子プロセスの環境はprocess.env
と同じになります。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
)と実行可能ファイルへの絶対パスでない限りspawn
を見つけることができなくなるため、ENOENT
はcommand
エラーを発生させます 。
PATH
が正しく設定されたら、次の手順に進みます。 ディレクトリかディレクトリのリストでなければなりません。最後のケースは普通です。
command
がPATH
で定義されているディレクトリの中に存在することを確認します ファイル名ENOENT
(すなわち、 'some-command')がcommand
で定義されたディレクトリの少なくとも1つに存在しない場合、SpawnはPATH
エラーを発行するかもしれません。
command
の正確な場所を見つけます。ほとんどのLinuxディストリビューションでは、これはwhich
コマンドを使って端末から実行できます。それはあなたに実行可能ファイルへの絶対パス(上記のように)を告げるか、それが見つからないかどうかを告げるでしょう。
コマンドが found の場合のwhichの使用例とその出力
> which some-command
some-command is /usr/bin/some-command
コマンドの使用例と が見つからない の場合の出力
> which some-command
bash: type: some-command: not found
プログラムのインストールミスが見つからないコマンドの最も一般的な原因です。 必要に応じて各コマンドのドキュメントを参照してインストールしてください。
commandが単純なスクリプトファイルの場合は、PATH
のディレクトリからアクセスできることを確認してください。 そうでない場合は、1に移動するか、またはリンクを張ってください。
PATH
が正しく設定されていてcommand
がそこからアクセス可能であると判断したら、spawn ENOENT
をスローしなくても子プロセスを生成できるはずです。
@DanielImfeldが指摘したように 、オプションに "cwd"を指定した場合、ENOENTがスローされますが、指定されたディレクトリは存在しません。
Windowsの解決策:spawn
を node-cross-spawn に置き換えます。たとえば、app.jsの冒頭にある以下のようにします。
(function() {
var childProcess = require("child_process");
childProcess.spawn = require('cross-spawn');
})();
@ 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
});
これは、bashがインストールされている限りcp.on('exit', fn)
イベントが常に発生するためです。そうしないと、最初に使用する場合は、cp.on('error', fn)
イベントが最初に発生する可能性があります。
これに遭遇するかもしれない人のために、他のすべての答えが助けにならず、あなたがWindows上にいるならば、現在 Windows上のspawn
の大きな問題 そして特定の呼び出しを引き起こす原因となるPATHEXT
環境変数があることを知ってくださいtargetコマンドのインストール方法によっては機能しません。
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})
私の場合、必要な依存システムリソースがインストールされていないために、このエラーが発生していました。
具体的には、ImageMagickを利用しているNodeJSアプリがあります。 npmパッケージがインストールされているにもかかわらず、コアのLinux ImageMagickがインストールされていません。私はImageMagickをインストールするためにapt-getをしました、そしてその後、すべてうまくいきました!
私は同じ問題に遭遇しました、しかし、私はそれを直す簡単な方法を見つけました。プログラムがユーザーによってPATHに追加された場合(例:通常のシステムコマンドが機能する場合)、spawn()
エラーと思われます。
これを修正するには、 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']);
実行されるモジュールがインストールされているか、それがノードモジュールでない場合はコマンドへのフルパスであることを確認します。
テストケースを実行している間、私はこの厄介な問題も経験していたので、それを乗り越えるために多くの方法を試しました。しかし、私にはうまくいく方法は メインファイルを含むディレクトリからテストランナーを実行することです これには nodejs spawn 関数が含まれます。
nodeProcess = spawn('node',params, {cwd: '../../node/', detached: true });
例えば、この ファイル名はtest.js なので、 それが入っているフォルダーに移動してください 。私の場合は、このようなテストフォルダです。
cd root/test/
それから あなたのテストランナーを実行します 私の場合はそのモカですので、それはこのようになります:
mocha test.js
私はそれを理解するために私の一日以上を無駄にしました。楽しい!!
より具体的なエラーメッセージを表示するには、spawnの代わりに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);
});
私の場合の解決策
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');
あなたがWindowsを使っているなら、あなたが知っているコマンドを発行することになるかもしれない引用を扱うときNode.jsはいくらか面白い仕事をします、しかし、Nodeで動かされるときはそうしません。例えば、次のような should work:
spawn('ping', ['"8.8.8.8"'], {});
しかし失敗します。トリックをするように思える引用符/類似物を扱うための幻想的に文書化されていないオプションwindowsVerbatimArguments
があります、ちょうどあなたのoptsオブジェクトに以下を追加するようにしてください:
const opts = {
windowsVerbatimArguments: true
};
そしてあなたの命令は元に戻ります。
spawn('ping', ['"8.8.8.8"'], { windowsVerbatimArguments: true });
Windowsでこの問題に遭遇しました。exec
とspawn
をまったく同じコマンド(引数を省略)で呼び出すと、exec
で問題なく動作しました(コマンドが$PATH
)、ただしspawn
はENOENTを返します。使用していたコマンドに.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']);
私は窓8のための同じエラーを得ました。問題はあなたのシステムパスの環境変数がないためです。システムのPATH変数に "C:\ Windows\System32 \"という値を追加します。
Debian LinuxシステムのVS Codeエディタ内からnode.jsプログラムをデバッグしようとしたときにこのエラーが発生しました。私はWindows上で同じことがうまくいったことに気づきました。私が「spawn」コマンドを書いていなかったので、ここで以前に与えられた解決策はあまり役に立ちませんでした。問題のあるコードは、おそらくMicrosoftによって書かれ、VS Codeプログラムの裏側に隠されていました。
次に、node.jsはWindowsではnodeと呼ばれていますが、Debian(そしておそらくUbuntuなどのDebianベースのシステム)ではnodejsと呼ばれています。だから私はエイリアスを作成しました - ルートターミナルから、私は走りました
ln -s/usr/bin/nodejs/usr/local/bin/node
これで問題は解決しました。 node.jsがnodejsと呼ばれているがnodeと呼ばれるプログラムを実行している場合、またはその逆の場合も、同じ手順または類似の手順がおそらくうまくいくでしょう。