Node.js 捕获生成后抛出的 ENOMEM 错误

IT技术 javascript node.js error-handling try-catch spawn
2021-02-27 18:02:45

我的 Node.js 脚本因使用spawn时抛出的 ENOMEM(内存不足)errnoException 而崩溃

错误:

child_process.js:935
  throw errnoException(process._errno, 'spawn');
        ^

Error: spawn ENOMEM
  at errnoException (child_process.js:988:11)
  at ChildProcess.spawn (child_process.js:935:11)
  at Object.exports.spawn (child_process.js:723:9)
  at module.exports ([...]/node_modules/zbarimg/index.js:19:23)

我已经在使用errorexit事件的侦听器,但是在出现此错误的情况下,它们都不会被触发。

我的代码:

zbarimg = process.spawn('zbarimg', [photo, '-q']);
zbarimg.on('error', function(err) { ... });
zbarimg.on('close', function(code) { ... }); 

可用的完整源代码

我能做些什么来防止脚本崩溃?如何捕获抛出的 ENOMEM 错误?

6个回答

我遇到了同样的问题,结果证明我的系统没有启用交换空间通过运行以下命令检查是否是这种情况free -m

vagrant@vagrant-ubuntu-trusty-64:~$ free -m
             total       used       free     shared    buffers     cached
Mem:          2002        233       1769          0         24         91
-/+ buffers/cache:        116       1885
Swap:            0          0          0

查看底行,我们可以看到总共有 0 字节的交换内存。不好。Node 可能会占用大量内存,如果内存耗尽时没有可用的交换空间,则必然会发生错误。

添加交换文件的方法因操作系统和发行版而异,但如果您像我一样运行 Ubuntu,则可以按照以下说明添加交换文件

  1. sudo fallocate -l 4G /swapfile 创建一个 4 GB 的交换文件
  2. sudo chmod 600 /swapfile 通过限制对 root 的访问来保护交换文件
  3. sudo mkswap /swapfile 将文件标记为交换空间
  4. sudo swapon /swapfile 启用交换
  5. echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstab在重新启动时保持交换文件(感谢您的提示,bman!)
这在生产服务器上是个好主意吗?我的理解是,当操作系统开始使用交换内存时,性能会急剧下降,因此最好为服务器设置足够的 RAM 来处理应用程序的需求,并积极寻找内存泄漏。
2021-04-26 18:02:45
仅供将来阅读此答案的任何人使用。重新启动时交换文件不是持久的。要使其持久化,您需要编辑 /etc/fstab 文件并在末尾添加一行:/swapfile none swap sw 0 0
2021-04-27 18:02:45
@josh,当 RAM 用完时,将发生以下两种情况之一——内存将被分页到交换文件,或者任何对额外内存的请求都将失败并导致意外结果。是的,使用交换文件时性能可能会下降,但我会在任何一天使用其他选项,尤其是在生产中。
2021-04-29 18:02:45
只是给我愚蠢的 VM 2 更多的 ram 演出解决了我的上述问题。
2021-05-18 18:02:45
在对这个答案进行了大量搜索之后,我只需要(并教我有关交换内存的知识)。强烈建议将此作为答案
2021-05-18 18:02:45

如果您在 AWS Lambda 中遇到过这个问题,您应该考虑增加分配给函数的内存。

您可以尝试使用以下命令更改节点使用的内存量: node ----max-old-space-size=1024 yourscript.js

--max-old-space-size=1024 将分配 1 gig 的内存。

默认情况下,节点将使用 512 mb 内存,但根据您的平台,您可能需要分配更多或更少的内存,以便在您需要时启动垃圾收集。

如果您的平台可用内存少于 500 mb,请尝试将内存使用量设置为 --max-old-space-size=256。

我遇到了同样的问题并通过 try / catch 修复:

try {
  zbarimg = process.spawn('zbarimg', [photo, '-q']);
} catch (err) {
  console.log(err);
}
zbarimg.on('error', function(err) { ... });
zbarimg.on('close', function(code) { ... }); 

我通过禁用和重新启用我的节点服务器解决了这个问题。