当我收到以下错误时:
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=production 的 spawn 函数
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
Node JS - Grunt 任务中的 child_process spawn('npm install') 导致 ENOENT 错误
运行“工头”任务致命错误:spawn 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
使用子进程 NodeJS 运行 exe 文件
节点:child_process.spawn 无法在 Java 上运行,即使它在路径中(ENOENT)
使用 NodeJS 产生 ENOENT 错误(与 PYTHON 相关)
图像大小调整在 node.js (partial.js) 中不起作用(未安装的依赖项)
npm install error ENOENT(构建依赖问题)
无法在 Windows 7 上安装 node.js - oracle 模块(构建依赖问题)
在 Windows 上使用 nodejs 安装 gulp 时出错(奇怪的情况)
exec
一样将整个命令作为字符串传递,而不是将命令作为第一个参数传递,将选项作为第二个参数的数组传递。例如,我在做 spawn( "adb logcat -c" )
而不是 spawn( "adb", [ "logcat", "-c" ] )
。
注意:此错误几乎总是由于该命令不存在、工作目录不存在或仅 Windows 错误引起。
我找到了一种特别简单的方法来了解以下根本原因:
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 步:确保以正确的方式调用 spawn
首先,查看 docs for child_process.spawn( command, args, options ):
使用给定的命令启动一个新进程,并在 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
有两种可能的情况:
您依赖默认生成行为,因此子进程环境将与 process.env 相同。您明确地传递了一个 env 对象以在 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 中定义的目录中
如果在 PATH
上定义的至少一个目录中不存在文件名 command
(即“some-command”),Spawn 可能会发出 ENOENT
错误。
找到 command
的确切位置。在大多数 linux 发行版上,这可以从终端使用 which
命令完成。它会告诉你可执行文件的绝对路径(如上),或者告诉你是否找不到它。
找到命令时 which 及其输出的示例用法
> which some-command
some-command is /usr/bin/some-command
未找到命令时 which 及其输出的示例用法
> which some-command
bash: type: some-command: not found
未找到命令的最常见原因是未安装的程序。如果需要,请参阅每个命令文档并安装它。
如果命令是一个简单的脚本文件,请确保它可以从 PATH
上的目录访问。 如果不是,请将其移至一个或创建一个链接。
一旦您确定 PATH
设置正确并且可以从中访问 command
,您应该能够生成您的子进程而不会抛出 spawn ENOENT
。
cwd
,则会抛出 ENOENT,但给定目录不存在。
spawn('some-command', ['--help'], { env: env });
(如本答案中的第 3 步所示)并传递自定义环境时,请务必指定 PATH
,例如:{ env: { PATH: process.env.PATH } }
。默认情况下, env 选项不会从当前 env 继承变量。
shell: true
传递给 spawn 选项来解决我的问题。
作为 @DanielImfeld pointed it,如果您在选项中指定“cwd”,则将抛出 ENOENT,但给定目录不存在。
cwd
路径中包含驱动器号:'c:/...' 而不仅仅是 '/...'
在 Windows 中,只需添加 shell: true
选项即可解决我的问题:
不正确:
const { spawn } = require('child_process');
const child = spawn('dir');
正确的:
const { spawn } = require('child_process');
const child = spawn('dir', [], {shell: true});
{ shell: true }
也适用于 MacOS。
Windows 解决方案:将 spawn
替换为 node-cross-spawn。例如在你的 app.js 开头这样:
(function() {
var childProcess = require("child_process");
childProcess.spawn = require('cross-spawn');
})();
var spawn = require('cross-spawn');
// Spawn NPM asynchronously var child = spawn('npm', ['list', '-g', '-depth', '0'], { stdio: 'inherit' });
对于 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})
shell: true
@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
});
但是,我建议这样做:
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)
事件。
child_process.exec
或将 shell: true
传递给 spawn
。
对于任何可能偶然发现这一点的人,如果所有其他答案都没有帮助并且您在 Windows 上,请知道当前有 a big issue with spawn
on Windows 和 PATHEXT
环境变量可能导致某些调用产生不工作,具体取决于如何目标命令已安装。
spawn
,只使用了 exec
。
如何研究引发错误的 spawn 调用:
使用 NODE_DEBUG=child_process,感谢 @karl-richter。简单,快速,2019 年 10 月
使用包装器来装饰 child_process.spawn,感谢 @jiaji-zhou。简单,快速,2015 年 1 月
漫长的过程,归功于@laconbass。复杂,时间成本,2014 年 12 月
已知的常见原因
环境问题 系统中不存在命令可执行文件(未安装依赖项)。请参阅 prominc 的答案命令可执行文件不存在于 PATH 环境变量指定的目录中。可执行二进制文件是使用不兼容的库编译的。请参阅 danilo-ramirez 回答仅 Windows 的错误/怪癖 '.cmd' 扩展名/外壳:是的。见李正回答管理员权限。见史蒂夫的回答 错误的 spawn('command', ['--argument', 'list'], { cwd, env, ...opts }) 用法 指定的工作目录 (opts.cwd) 不存在·见 leeroy-brun 的answer 命令字符串中的参数列表 spawn('command --wrong --argument list') 命令字符串中的环境变量 spawn('ENV_VAR=WRONG command') 参数列表 指定为字符串的数组 spawn('cmd', '--argument list ') 未设置 PATH 环境变量 spawn('cmd', [], { env: { variable } } => spawn('cmd', [], { env: { ...process.env, variable } }
ENOENT 有 2 个可能的来源: 您正在编写的代码 您所依赖的代码 当来源是您所依赖的代码时,通常原因是环境问题(或 Windows 怪癖)
就我而言,由于未安装必要的依赖系统资源,我收到了这个错误。
更具体地说,我有一个使用 ImageMagick 的 NodeJS 应用程序。尽管安装了 npm 包,但核心 Linux ImageMagick 并未安装。我做了一个 apt-get 来安装 ImageMagick,之后一切都很好!
yarn
(安装)修复它
brew install imagemagick
在任何人花费大量时间调试此问题之前,大多数情况下可以通过删除 node_modules
并重新安装软件包来解决。
安装:
如果存在锁定文件,您可以使用
yarn install --frozen-lockfile
或者
npm ci
分别。如果不是那么
yarn install
或者
npm i
您要更改 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
。这将为您提供在哪个目录中调用了哪些命令行的信息,通常最后一个细节是失败的原因。
我遇到了同样的问题,但我找到了一个简单的方法来解决它。如果程序已被用户添加到 PATH 中(例如正常的系统命令有效),则似乎是 spawn()
错误。
要解决此问题,您可以使用 which 模块 (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']);
使用 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);
});
确保要执行的模块已安装或命令的完整路径(如果它不是节点模块)
我在运行测试用例时也遇到了这个烦人的问题,所以我尝试了很多方法来解决它。但是对我有用的方法是从包含主文件的目录中运行测试运行程序,其中包含你的 nodejs spawn 函数,如下所示:
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');
.cmd
的节点 repl 中工作,但在打字稿开玩笑测试中失败。 - 这个错误可能很难弄清楚,这个答案值得更多的支持。
.cmd
扩展程序
我在 Windows 上遇到了这个问题,其中使用完全相同的命令(省略参数)调用 exec
和 spawn
对于 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']);
我发现的一个案例不在此列表中,但值得添加:
在 Alpine Linux 上,如果可执行文件不兼容,Node 将出现 ENOENT 错误。
Alpine 需要带有 libc
的二进制文件。已使用 glibc
作为系统调用的包装器编译的可执行文件(例如,作为 chromium 的一部分的 chrome
)在被 spawn
调用时将失败并显示 ENOENT。
尝试从 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 但您正在运行的程序期望它被称为 node 的其他情况下工作,反之亦然。
如果你在 Windows 上,Node.js 在处理引号时会做一些有趣的事情,这可能会导致你发出一个你知道可以从控制台运行的命令,但在 Node 中运行时却不行。例如以下应该工作:
spawn('ping', ['"8.8.8.8"'], {});
但失败了。有一个非常无证的选项 windowsVerbatimArguments
用于处理引号/类似的似乎可以解决问题,只需确保将以下内容添加到您的 opts 对象:
const opts = {
windowsVerbatimArguments: true
};
你的命令应该恢复正常。
spawn('ping', ['"8.8.8.8"'], { windowsVerbatimArguments: true });
尽管对于某些人来说这可能是环境路径或其他问题,但我刚刚在 Windows 10 上安装了适用于 Visual Studio Code 的 Latex Workshop 扩展,并在尝试构建/预览 PDF 时看到了此错误。以管理员身份运行 VS Code 为我解决了这个问题。
在我的情况下删除节点,删除所有 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
。更改该配置解决了我的问题。
尝试了一切都没有用,我的系统有不同的问题。
我的工作解决方案是运行命令: npm config set script-shell "C:\Program Files\git\bin\bash.exe"
npm
本身有关,而不是与节点的 child_process.spawn()
有关。似乎是一个 Windows 怪癖
我在 Windows 8 上遇到了同样的错误。问题是因为缺少系统路径的环境变量。将“C:\Windows\System32\”值添加到系统 PATH 变量中。
模拟器上的本地开发
确保在本地安装了该软件包。通过用 exec
更改 spawn
命令,我得到了一个更详细的错误,并发现我没有安装包。只需运行,检查包是否存在:
brew install imagemagick
将 C:\Windows\System32\
添加到 path
环境变量。
脚步
转到我的计算机和属性单击高级设置然后在环境变量上选择路径然后单击编辑粘贴以下内容(如果不存在):C:\Windows\System32\ 关闭命令提示符运行您要运行的命令
https://i.stack.imgur.com/XCTAf.png
不定期副业成功案例分享
spawn()
更改为exec()
并重试。exec()
将告诉您它尝试运行什么命令。