如何在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)
我可以按照什么程序来修复?
作者注意 :许多与这个错误的问题,鼓励我发布这个问题,为将来的参考。
相关问题:
- 使用带有NODE_ENV =产生的产卵函数
- node.js child_process.spawn ENOENT错误 – 仅在supervisord下
- 产生ENOENT node.js错误
- https://stackoverflow.com/questions/27603713/nodejs-spawn-enoent-error-on-travis-calling-global-npm-package
- 在Grunt任务中的节点JS – child_process spawn('npm install')导致ENOENT错误
- 运行“领班”任务致命错误:产生ENOENT
- 节点js中未处理的错误事件错误:在errnoException(child_process.js:975:11)处产生ENOENT
- Node.js SpookyJS:执行hello.js时出错
- https://stackoverflow.com/questions/26572214/run-grunt-on-a-directory-nodewebkit
- 使用Child Process NodeJS运行exe文件
- Node:child_process.spawn即使在路径中也不能在Java上工作(ENOENT)
- 用NodeJS产生ENOENT错误 (PYTHON相关)
- 图像大小调整在node.js(partial.js) (未安装的依赖项)中不起作用
- npm安装错误ENOENT (构建依赖问题)
- 无法在Windows 7上安装node.js – oracle模块 (构建依赖问题)
- 在windows上使用nodejs安装gulp时出错 (奇怪的情况)
我发现一个特别简单的方法来得到这个根本原因的想法:
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无法找到可执行文件来解决问题。
第一步:确保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:确保在PATH
定义的目录中存在command
如果文件名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
。
Windows解决方案:用节点交叉产卵替换产卵 。 例如像你的app.js的开始:
(function() { var childProcess = require("child_process"); childProcess.spawn = require('cross-spawn'); })();
正如@DanielImfeld指出的那样 ,如果在选项中指定“cwd”,ENOENT将会被抛出,但是给定的目录不存在。
对于任何可能偶然发现的人来说,如果所有其他的答案都不能帮助你,并且你在Windows上,那么知道在Windows上spawn
一个大问题,并且PATHEXT
环境变量会导致某些调用产生不能工作关于如何安装目标命令。
@ 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 });
在我的情况下,由于没有安装必要的依赖系统资源,我得到此错误。
更具体地说,我有一个使用ImageMagick的NodeJS应用程序。 尽管安装了npm软件包,但未安装核心Linux ImageMagick。 我做了一个apt-get来安装ImageMagick,之后所有的工作都很好!
对于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})
我遇到了同样的问题,但我找到了一个简单的方法来解决它。 如果程序已被用户添加到PATH(例如正常的系统命令工作),它似乎是spawn()
错误。
要解决这个问题,你可以使用哪个模块( 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']);
如果不是节点模块,请确保要执行的模块已安装或完整路径
我试图在Debian Linux系统上的VS Code编辑器中调试node.js程序时出现这个错误。 我注意到在Windows上同样的事情工作正常。 之前给出的解决方案没有太多的帮助,因为我没有写任何“spawn”命令。 有问题的代码大概是由微软写的,隐藏在VS Code程序的底层。
接下来我注意到,node.js在Windows上被称为node,但在Debian上(大概是在基于Debian的系统上,比如Ubuntu),它被称为nodejs。 所以我创建了一个别名 – 从一个根终端,我跑了
ln -s / usr / bin / nodejs / usr / local / bin / node
这解决了这个问题。 在其他情况下,相同或相似的过程可能会起作用,其他情况下,您的node.js被称为nodejs,但是您正在运行一个程序,期望它被称为节点,反之亦然。
我得到了Windows 8相同的错误。问题是因为您的系统路径的环境变量是缺少的。 将“C:\ Windows \ System32 \”值添加到您的系统PATH变量。
使用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); });
如果你在Windows上,Node.js在处理报价时会做一些有趣的事情,这些报价可能导致你发出一个你知道在控制台上工作的命令,但是在Node中运行的命令不会。 例如以下应该工作:
spawn('ping', ['"8.8.8.8"'], {});
但失败。 有一个很windowsVerbatimArguments
没有记录的选项windowsVerbatimArguments
用于处理引用/类似的似乎做的伎俩,只要确保将以下添加到您的opts对象:
const opts = { windowsVerbatimArguments: true };
你的命令应该恢复正常。
spawn('ping', ['"8.8.8.8"'], { windowsVerbatimArguments: true });
将C:\Windows\System32\
到path
环境变量。
脚步
-
转到我的电脑和属性
-
点击高级设置
-
然后在环境变量上
-
选择
Path
,然后点击编辑 -
粘贴以下(如果尚不存在):
C:\Windows\System32\
-
关闭命令提示符
-
运行你想运行的命令