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
这个错误的问题是,错误消息中几乎没有信息告诉你调用站点在哪里,即找不到哪个可执行文件/命令,特别是当你有一个很大的代码库,那里有大量的spawn调用。另一方面,如果我们知道导致错误的确切命令,那么我们可以按照@laconbass' answer来解决问题。
我找到了一种非常简单的方法来确定哪个命令导致问题,而不是像@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找不到可执行文件来解决问题。
如果它不是节点模块,请确保要安装的模块或命令的完整路径
尝试从Debian Linux系统上的VS Code编辑器中调试node.js程序时出现此错误。我注意到在Windows上同样的功能正常。之前给出的解决方案没有多大帮助,因为我没有编写任何“spawn”命令。违规代码大概是由Microsoft编写的,隐藏在VS Code程序的引擎盖下。
接下来我注意到node.js在Windows上被称为节点,但在Debian上(可能是在基于Debian的系统上,如Ubuntu),它被称为nodejs。所以我创建了一个别名 - 从根终端,我跑了
ln -s / usr / bin / nodejs / usr / local / bin / node
这解决了这个问题。相同或类似的过程可能适用于node.js被称为nodejs的其他情况,但是你正在运行一个程序,它希望它被称为节点,反之亦然。
我在Windows 8中遇到了同样的错误。问题是因为缺少系统路径的环境变量。将“C:\ Windows \ System32 \”值添加到系统PATH变量中。
如果您使用的是Windows Node.js在处理引号时会做一些有趣的事情,这可能会导致您发出一个您知道在控制台上运行的命令,但在Node中运行时则不会。例如,以下应该工作:
// 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']);
但失败了。有一个奇怪的未记录的选项require('child_process').exec
用于处理引号/类似似乎可以做到这一点,只需确保将以下内容添加到您的opts对象:
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);
});
你的命令应该重新开始。
spawn('ping', ['"8.8.8.8"'], {});
在运行我的测试用例时,我也遇到了这个烦人的问题,所以我尝试了很多方法来解决它。但对我有用的方法是从包含你的主文件的目录运行你的测试运行器,其中包含你的nodejs spawn函数,如下所示:
windowsVerbatimArguments
例如,此文件名是test.js,因此只需移动到包含它的文件夹即可。在我的情况下,它是这样的测试文件夹:
const opts = {
windowsVerbatimArguments: true
};
然后从我的情况下运行你的测试运行器它的摩卡,所以它将是这样的:
spawn('ping', ['"8.8.8.8"'], { windowsVerbatimArguments: true });
我已经浪费了一天多的时间来搞清楚这一点。请享用!!
我的解决方案
nodeProcess = spawn('node',params, {cwd: '../../node/', detached: true });
将cd root/test/
添加到mocha test.js
环境变量中。
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');
然后单击编辑C:\Windows\System32\
spawn
首先,回顾一下docs for child_process.spawn( command, args, options ):
使用给定的
command
启动一个新进程,在args
中使用命令行参数。如果省略,args
默认为空数组。第三个参数用于指定其他选项,默认为:
{ cwd: undefined, env: process.env }
使用
env
指定新进程可见的环境变量,默认为process.env
。
确保您没有在command
中放置任何命令行参数,并且整个spawn
调用有效。继续下一步。
搜索每次调用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
再做这一步,直到他们不这样做。在继续下一步之前,您必须识别发出错误的侦听器。
$PATH
有两种可能的情况:
spawn
行为,因此子进程环境将与process.env
相同。在这两种情况下,您都必须检查生成的子进程将使用的环境对象上的env
键。
方案1的示例
spawn
方案2的示例
options
缺少PATH
(即它的// inspect the PATH key on process.env
console.log( process.env.PATH );
spawn('some-command', ['--help']);
)将导致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
(即'some-command'),则Spawn可能会发出PATH
错误。
找到ENOENT
的确切位置。在大多数Linux发行版中,这可以通过command
命令从终端完成。它将告诉您可执行文件的绝对路径(如上所述),或告诉您是否找不到它。
找到命令时的示例用法及其输出
PATH
未找到命令时的示例用法及其输出
command
安装错误的程序是找不到命令的最常见原因。如果需要,请参阅每个命令文档并进行安装。
当命令是一个简单的脚本文件时,请确保它可以从which
上的目录访问。如果不是,请将其移至一个或链接到它。
一旦你确定> which some-command
some-command is /usr/bin/some-command
被正确设置并且可以从中访问> which some-command
bash: type: some-command: not found
,你应该能够在不抛出PATH
的情况下生成你的子进程。
如PATH
,如果在选项中指定“cwd”,则会抛出ENOENT,但给定目录不存在。
Windows解决方案:用command
替换spawn ENOENT
。例如,在app.js的开头就像这样:
@DanielImfeld pointed it
@ laconbass的回答对我有帮助,可能是最正确的。
我来到这里是因为我错误地使用了spawn。举个简单的例子:
这是不正确的:
spawn
这是不正确的:
node-cross-spawn
这是对的:
(function() {
var childProcess = require("child_process");
childProcess.spawn = require('cross-spawn');
})();
但是,我建议这样做:
const s = cp.spawn('npm install -D suman', [], {
cwd: root
});
这是因为只要安装了bash,const s = cp.spawn('npm', ['install -D suman'], {
cwd: root
});
事件将始终触发,否则,如果我们以第一种方式使用它,const s = cp.spawn('npm', ['install','-D','suman'], {
cwd: root
});
事件可能会先触发,如果我们直接启动'npm'。
对于任何可能偶然发现这一点的人,如果所有其他答案都没有帮助并且你在Windows上,请知道当前有const s = cp.spawn('bash');
s.stdin.end(`cd "${root}" && npm install -D suman`);
s.once('exit', code => {
// exit
});
和cp.on('exit', fn)
环境变量可能导致某些调用spawn不起作用,具体取决于目标命令的方式安装。
对于Windows上的ENOENT,cp.on('error', fn)
修复它。
例如用以下代码替换spawn('npm',[' - v'],{stdio:'inherit'}):
spawn
on WindowsPATHEXT
在我的情况下,由于没有安装必要的依赖系统资源,我得到了这个错误。
更具体地说,我有一个使用ImageMagick的NodeJS应用程序。尽管安装了npm软件包,但未安装核心Linux ImageMagick。我做了一个apt-get来安装ImageMagick,之后一切都很棒!
我遇到了同样的问题,但我找到了一种简单的方法来解决它。如果用户已将程序添加到PATH(例如,正常的系统命令工作),则看起来是https://github.com/nodejs/node-v0.x-archive/issues/2318#issuecomment-249355505错误。
要解决此问题,您可以使用spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['-v'], {stdio: 'inherit'})
模块(spawn('npm', ['-v'], {stdio: 'inherit', shell: true})
):
spawn()