我如何调试“错误:生成enoent”;在node . js ?

当我得到以下错误:

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)

我该采取什么程序来修理呢?

作者注:这个错误的很多问题鼓励我张贴这个问题,以供将来参考。

相关问题:

644943 次浏览

步骤1:确保spawn被正确调用

首先,回顾child_process的文档。衍生(命令,参数,选项):

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

第三个参数用于指定额外的选项,默认为:

{ cwd: undefined, env: process.env }

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

确保你没有在__ABC0中放入任何命令行参数,并且整个spawn调用都是有效的。执行下一步。

步骤2:识别发出错误事件的事件发射器

在源代码中搜索对spawnchild_process.spawn的每次调用。

spawn('some-command', [ '--help' ]);

并为'error'事件附加一个事件监听器,这样你就会注意到确切的事件发射器将它作为'Unhandled'抛出。调试之后,可以删除该处理程序。

spawn('some-command', [ '--help' ])
.on('error', function( err ){ throw err })
;

执行后,您将获得注册'error'侦听器的文件路径和行号。喜欢的东西:

/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. 你是在显式地通过options参数将一个env对象传递给spawn

在这两种情况下,都必须检查派生子进程将使用的环境对象上的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 });

缺少__ABC0(即,它是__ABC1)将导致__ABC2发出ENOENT错误,因为它不可能找到任何command,除非它是可执行文件的绝对路径。

PATH被正确设置时,继续下一步。应该是一个目录,或者目录列表。最后一种情况很常见。

步骤4:确保command存在于PATH中定义的目录中

如果文件名command(即'some-command')在PATH上定义的至少一个目录中不存在,Spawn可能会发出ENOENT错误。

找到command的确切位置。在大多数linux发行版上,这可以从终端使用which命令完成。它会告诉你可执行文件的绝对路径(如上所述),或者告诉你是否没有找到它。

当命令为found时,which及其输出的示例用法

> which some-command
some-command is /usr/bin/some-command

当命令为not found时,which及其输出的示例用法

> which some-command
bash: type: some-command: not found

错误安装的程序是导致not found命令的最常见原因。如果需要,请参考每个命令文档并安装它。

当命令是一个简单的脚本文件时,确保它可以从PATH上的目录访问。如果不是,要么将它移动到1,要么创建一个链接到它。

一旦你确定PATH被正确设置并且可以从它访问command,你应该能够在不抛出spawn ENOENT的情况下派生子进程。

注意:此错误几乎总是由于命令不存在、工作目录不存在或由windows特有的错误引起的。

我发现了一个特别简单的方法来了解问题的根本原因:

Error: spawn ENOENT

这个错误的问题是,在错误消息中很少有信息告诉你调用的位置,即没有找到哪个可执行/命令,特别是当你有一个很大的代码库,其中有很多衍生调用时。另一方面,如果我们知道导致错误的确切命令,那么我们可以通过@laconbass的回答来解决问题。

我发现了一种非常简单的方法来发现导致问题的命令,而不是像@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不能找到可执行文件来解决这个问题。

在我的例子中,由于没有安装必要的依赖系统资源,我抛出了这个错误。

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

对于任何可能偶然发现这一点的人,如果所有其他答案都没有帮助,并且你是在Windows上,要知道当前有Windows上spawn的一个大问题PATHEXT环境变量,可以导致某些调用生成不工作,这取决于目标命令的安装方式。

Windows解决方案:将spawn替换为node-cross-spawn。例如,在你的app.js的开头:

(function() {
var childProcess = require("child_process");
childProcess.spawn = require('cross-spawn');
})();

当我试图在Debian Linux系统上从VS Code编辑器中调试node.js程序时,我得到了这个错误。我注意到同样的事情在Windows上也可以正常工作。这里之前给出的解决方案没有多大帮助,因为我没有编写任何“衍生”命令。违规代码可能是由微软编写的,并隐藏在VS code程序的引擎盖下。

接下来,我注意到node.js在Windows上被称为node,但在Debian上(可能在基于Debian的系统上,如Ubuntu),它被称为nodejs。所以我创建了一个别名,从根终端运行

Ln -s /usr/bin/nodejs /usr/local/bin/node

这就解决了问题。同样或类似的过程可能也适用于其他情况,即你的node.js被称为nodejs,但你运行的程序希望它被称为node,反之亦然。

@laconbass的回答帮助了我,可能是最正确的。

我来这里是因为我错误地使用了产卵。 作为一个简单的例子:

这是不正确的:

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)事件总是会触发,否则,如果我们以第一种方式使用它,如果我们直接启动'npm', cp.on('error', fn)事件可能会先触发。

我在windows 8上得到了同样的错误。问题是由于系统路径的环境变量丢失。将“C:\Windows\System32\”值添加到系统PATH变量中。

我遇到了同样的问题,但我找到了一个简单的方法来解决它。 如果程序已被用户添加到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']);

作为@DanielImfeld指出,如果你在选项中指定了"cwd",但给定的目录不存在,ENOENT将被抛出。

C:\Windows\System32\添加到环境变量path中。

步骤

  1. 转到我的计算机和属性

  2. 点击高级设置

  3. 然后在环境变量

  4. 选择Path,然后单击edit

  5. 如果不存在,粘贴以下内容:C:\Windows\System32\

  6. 关闭命令提示符

  7. 运行您想要运行的命令

Windows 8环境变量截图

对于Windows上的ENOENT, https://github.com/nodejs/node-v0.x-archive/issues/2318#issuecomment-249355505修复它。

如更换产卵(npm, [' v '], {stdio:“继承”}):

  • 所有node.js版本:

    spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['-v'], {stdio: 'inherit'})
    
  • for node.js 5.x and later:

    spawn('npm', ['-v'], {stdio: 'inherit', shell: true})
    

如果不是节点模块,则确保要执行的模块已安装或命令的全路径

使用require('child_process').exec代替spawn来获得更具体的错误消息!

例如:

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用于处理引号/类似内容,它似乎可以做到这一点,只需确保将以下内容添加到opts对象中:

const opts = {
windowsVerbatimArguments: true
};

你的指挥部应该能恢复正常工作了。

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

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

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

例如,这个文件名为test.js,所以就是移动到包含它的文件夹。在我的例子中,它是这样的测试文件夹:

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');

我在Windows上遇到了这个问题,用完全相同的命令(省略参数)调用execspawn对于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']);

你正在改变env选项吗?

然后看看这个答案。


我试图生成一个节点进程和TIL,当你生成时,你应该扩展现有的环境变量,否则你将失去PATH环境变量和其他可能重要的变量。

这就是我的解决方案:

const nodeProcess = spawn('node', ['--help'], {
env: {
// by default, spawn uses `process.env` for the value of `env`
// you can _add_ to this behavior, by spreading `process.env`
...process.env,
OTHER_ENV_VARIABLE: 'test',
}
});

如果你遇到的应用程序的源代码无法修改,你可以考虑将环境变量NODE_DEBUG设置为child_process来调用它,例如NODE_DEBUG=child_process yarn test。这将为您提供在哪个目录中调用了哪些命令行,通常最后一个细节是失败的原因。

简单地添加shell: true选项解决了我的问题:

不正确的:

const { spawn } = require('child_process');
const child = spawn('dir');

正确的:

const { spawn } = require('child_process');
const child = spawn('dir', [], {shell: true});

在任何人花费大量时间调试这个问题之前,大多数时候它可以通过删除node_modules并重新安装包来解决。

如何安装:

如果存在锁文件,您可以使用

yarn install --frozen-lockfile

npm ci

各自的。如果不是的话

yarn install

npm i

虽然对某些人来说这可能是一个环境路径或其他问题,但我刚刚在Windows 10上为Visual Studio Code安装了Latex Workshop扩展,并在尝试构建/预览PDF时看到了这个错误。作为管理员运行VS Code为我解决了这个问题。

如何研究刷出调用引起的错误:

已知的常见原因

  1. < p >环境问题

    • 该命令可执行文件在系统中不存在(依赖项未安装)。参见凸起的答案
    • 命令可执行文件不存在于由PATH环境变量指定的目录中。
    • 可执行二进制文件是用不兼容的库编译的。danilo-ramirez回答
  2. < p >仅适用于windows的bug /怪癖

  3. 错误的spawn('command', ['--argument', 'list'], { cwd, env, ...opts })用法

    • 指定的工作目录(opts.cwd)不存在
    • 命令String spawn('command --wrong --argument list')中的参数列表
    • 命令字符串spawn('ENV_VAR=WRONG command')中的环境变量
    • 参数列表Array指定为String spawn('cmd', '--argument list')
    • 取消设置PATH env变量spawn('cmd', [], { env: { variable } } =>spawn('cmd', [], { env: { ...process.env, variable } }

ENOENT有两个可能的来源:

  1. 您正在编写的代码
  2. 您依赖的代码

当origin是你依赖的代码时,通常的原因是环境问题(或windows怪癖)


在我的情况下,删除节点,删除所有AppData/Roaming/npm和AppData/Roaming/npm-cache,并安装节点再次解决问题。

最近我也遇到了类似的问题。

Starting the development server...


events.js:174
throw er; // Unhandled 'error' event
^


Error: spawn null ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:240:19)
at onErrorNT (internal/child_process.js:415:16)
at process._tickCallback (internal/process/next_tick.js:63:19)
Emitted 'error' event at:
at Process.ChildProcess._handle.onexit (internal/child_process.js:246:12)
at onErrorNT (internal/child_process.js:415:16)
at process._tickCallback (internal/process/next_tick.js:63:19)
error Command failed with exit code 1.


这是由于在BROWSER.env文件中有错误的配置。我有BROWSER=null,但它必须是BROWSER=none。改变配置解决了我的问题。

试了所有的都没用,我的系统有不同的问题。

我的解决方案是 运行命令: C:\Program Files\git\bin\bash.exe&

我发现一个案例不在这个列表中,但它值得添加:

在Alpine Linux上,如果可执行文件不兼容,Node将会出现ENOENT错误。

Alpine期望使用libc的二进制文件。用glibc编译的可执行文件(例如chrome作为chromium的一部分)作为系统调用的包装器,当由spawn调用时,将在ENOENT中失败。

模拟器上的本地开发

确保将包安装在本地。通过用exec更改spawn命令,我得到了一个更详细的错误,并发现我没有安装包。简单地运行,检查包是否存在:

brew install imagemagick

Source .

对我来说,我在package.json中做了以下更改。

  "version": "0.0.0",
"scripts": {
"dev": "vite --open",    // delete this line
"dev": "vite",           // with this one
.....
}