如何在node.js上调试“错误:生成ENOENT”?

问题描述 投票:275回答:17

当我收到以下错误:

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.js debugging error-handling child-process spawn
17个回答
199
投票

我找到了一种特别简单的方法来了解其根本原因:

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找不到可执行文件来解决问题。


1
投票

如果它不是节点模块,请确保要安装的模块或命令的完整路径


0
投票

尝试从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的其他情况,但是你正在运行一个程序,它希望它被称为节点,反之亦然。


0
投票

我在Windows 8中遇到了同样的错误。问题是因为缺少系统路径的环境变量。将“C:\ Windows \ System32 \”值添加到系统PATH变量中。


0
投票

使用which而不是spawn来获取更具体的错误消息!

例如:

npm install --save which

0
投票

如果您使用的是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"'], {});

0
投票

在运行我的测试用例时,我也遇到了这个烦人的问题,所以我尝试了很多方法来解决它。但对我有用的方法是从包含你的主文件的目录运行你的测试运行器,其中包含你的nodejs spawn函数,如下所示:

windowsVerbatimArguments

例如,此文件名是test.js,因此只需移动到包含它的文件夹即可。在我的情况下,它是这样的测试文件夹:

const opts = {
    windowsVerbatimArguments: true
};

然后从我的情况下运行你的测试运行器它的摩卡,所以它将是这样的:

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

我已经浪费了一天多的时间来搞清楚这一点。请享用!!


0
投票

我的解决方案

nodeProcess = spawn('node',params, {cwd: '../../node/', detached: true });

-1
投票

cd root/test/ 添加到mocha test.js 环境变量中。

脚步

  1. 转到我的电脑和财产
  2. 单击高级设置
  3. 然后是环境变量
  4. 选择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'); 然后单击编辑
  5. 如果尚未存在,请粘贴以下内容:C:\Windows\System32\
  6. 关闭命令提示符
  7. 运行要运行的命令


101
投票

第1步:确保以正确的方式调用spawn

首先,回顾一下docs for child_process.spawn( command, args, options )

使用给定的command启动一个新进程,在args中使用命令行参数。如果省略,args默认为空数组。

第三个参数用于指定其他选项,默认为:

{ cwd: undefined, env: process.env }

使用env指定新进程可见的环境变量,默认为process.env

确保您没有在command中放置任何命令行参数,并且整个spawn调用有效。继续下一步。

第2步:确定发出错误事件的事件发射器

搜索每次调用spawnchild_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

再做这一步,直到他们不这样做。在继续下一步之前,您必须识别发出错误的侦听器。

第3步:确保设置了环境变量$PATH

有两种可能的情况:

  1. 您依赖于默认的spawn行为,因此子进程环境将与process.env相同。
  2. 你在qazxsw poi论证中明确地将qazxsw poi对象传递给qazxsw poi。

在这两种情况下,您都必须检查生成的子进程将使用的环境对象上的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后,请继续执行下一步。它应该是目录或目录列表。最后一种情况是通常的。

第4步:确保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的情况下生成你的子进程。


29
投票

PATH,如果在选项中指定“cwd”,则会抛出ENOENT,但给定目录不存在。


24
投票

Windows解决方案:用command替换spawn ENOENT。例如,在app.js的开头就像这样:

@DanielImfeld pointed it

22
投票

@ 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'。


16
投票

对于任何可能偶然发现这一点的人,如果所有其他答案都没有帮助并且你在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不起作用,具体取决于目标命令的方式安装。


16
投票

对于Windows上的ENOENT,cp.on('error', fn)修复它。

例如用以下代码替换spawn('npm',[' - v'],{stdio:'inherit'}):


6
投票

在我的情况下,由于没有安装必要的依赖系统资源,我得到了这个错误。

更具体地说,我有一个使用ImageMagick的NodeJS应用程序。尽管安装了npm软件包,但未安装核心Linux ImageMagick。我做了一个apt-get来安装ImageMagick,之后一切都很棒!


2
投票

我遇到了同样的问题,但我找到了一种简单的方法来解决它。如果用户已将程序添加到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()
© www.soinside.com 2019 - 2024. All rights reserved.