Node.js перехватывает ошибку ENOMEM, возникающую после появления


84

Мой сценарий Node.js аварийно завершает работу из-за выброса исключения errnoException ENOMEM (Out of memory) при использовании spawn .

Ошибка:

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)

Я уже использую слушатель для errorи exitсобытия, но не из них увольняет в случае этой ошибки.

Мой код:

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

Доступен полный исходный код .

Что я могу сделать, чтобы предотвратить сбой сценария? Как мне отловить выданную ошибку ENOMEM?

Благодаря!


У вас есть пример изображения, которое можно использовать для воспроизведения проблемы?
mscdex 04

Это происходит, когда серверу не хватает памяти и его невозможно воспроизвести с определенным изображением. Это затрудняет тестирование: - /
tobi

Что ты делаешь внутри errorобработчика?
mscdex 06

1
Вы нашли решение этой проблемы?
sffc 08

2
Я думаю, что это фундаментальный недостаток использования fork()(основного системного вызова). См github.com/nodejs/node/issues/25382
ZachB

Ответы:


204

У меня была та же проблема, и, как оказалось, в моей системе не было включено пространство подкачки . Проверьте, так ли это, запустив команду 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 байт памяти подкачки. Не хорошо. Узел может изрядно потреблять память, и если при исчерпании памяти не будет свободного места для подкачки, неизбежны ошибки.

Метод добавления файла подкачки зависит от операционной системы и дистрибутива, но если вы используете Ubuntu, как я, вы можете следовать этим инструкциям по добавлению файла подкачки :

  1. sudo fallocate -l 4G /swapfile Создайте файл подкачки размером 4 гигабайта
  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 !)

15
Просто примечание для тех, кто в будущем будет читать этот ответ. Файл подкачки не сохраняется при перезагрузке. Чтобы сделать его постоянным, вам нужно отредактировать файл / etc / fstab и добавить в конец строку: / swapfile none swap sw 0 0
bman 05

Просто предоставив моей глупой виртуальной машине еще 2 гига оперативной памяти, я решил мою проблему.
Томсон Комер

2
Это хорошая идея для рабочего сервера? Насколько я понимаю, когда ОС начинает использовать память подкачки, производительность может резко упасть, поэтому лучше установить на сервере достаточно оперативной памяти, чтобы удовлетворить потребности приложений, и активно искать утечки памяти.
Джош

2
@josh, когда заканчивается ОЗУ, произойдет одно из двух: либо память будет выгружена в файл подкачки, либо любые запросы на дополнительную память завершатся ошибкой с неожиданными результатами. Да, производительность может снизиться при использовании файла подкачки, но я воспользуюсь этим в любой момент по сравнению с другим вариантом, особенно в производственной среде .
Kaivosukeltaja 01

У меня не удваивалась память и нужно изменить размер? Как мне это сделать?
Джек

5

Если вы когда-нибудь столкнетесь с этой проблемой в AWS Lambda, вам следует подумать об увеличении памяти, выделенной для функции.


2

Вы можете попробовать изменить объем памяти, используемый узлом, с помощью этой команды: node ----max-old-space-size=1024 yourscript.js

--max-old-space-size = 1024 выделит 1 гигабайт памяти.

По умолчанию node будет использовать 512 МБ оперативной памяти, но в зависимости от вашей платформы вам может потребоваться выделить больше или меньше, чтобы сборка мусора запускалась, когда вам это нужно.

Если на вашей платформе доступно менее 500 МБ оперативной памяти, попробуйте установить для использования памяти значение --max-old-space-size = 256.


1

У меня была такая же проблема и исправлена ​​с помощью try / catch:

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


-6

Вы должны сбросить выходные данные вызываемого процесса!

Пример на Python выглядит так:

import sys
...
sys.stdout.flush()

это не питон
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.