如何在node.js上调试“错误:产生ENOENT”?
当我收到以下错误:
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的答案来解决问题。
我发现了一个非常简单的方法来找出哪个命令导致问题,而不是像在@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无法找到可执行文件来解决问题。
第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' ]);
并在那里附加一个事件监听器来处理'错误'事件,所以你会注意到将它抛出为'未处理'的确切的事件发射器。 调试后,该处理程序可以被删除。
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
有两种可能的情况:
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
,继续下一步。 它应该是一个目录或一个目录列表。 最后一种情况是平常的。
步骤4:确保command
存在于PATH
定义的目录中
如果文件名command
(即'some-command')在PATH
定义的至少一个目录中不存在,则Spawn可能会发出ENOENT
错误。
找到command
的确切位置。 在大多数Linux发行版中,这可以通过使用which
命令从终端完成。 它会告诉你可执行文件的绝对路径(如上所述),或者告诉你是否找不到它。
在找到命令时使用哪一个及其输出的示例
> which some-command
some-command is /usr/bin/some-command
没有找到命令时使用哪个命令及其输出的示例
> which some-command
bash: type: some-command: not found
未安装程序是找不到命令的最常见原因。 如有需要,请参阅每个命令文档并进行安装。
当命令是简单的脚本文件时,请确保它可以从PATH
上的目录访问。 如果不是,则将其移动到一个或建立一个链接。
一旦你确定PATH
被正确设置并且command
可以从其中访问,你应该能够产生你的子进程而不会抛出子spawn ENOENT
。
正如@DanielImfeld指出的那样,如果在选项中指定“cwd”,ENOENT将被抛出,但给定的目录不存在。
链接地址: http://www.djcxy.com/p/65827.html上一篇: How do I debug "Error: spawn ENOENT" on node.js?
下一篇: How to make Grunt Deploy use global NPM modules instead of local ones