Bash fork невозможно выделить память
Я использую Ubuntu 14.04. Недавно, когда я вхожу в систему через SSH со своим пользователем с sudo полномочиями, каждая команда, я выполняю результаты в, “Не может выделить память” ошибка. Вот некоторые, я попробовал в своей консоли
Даже если я пробую sudo reboot now Я получаю вышеупомянутую ошибку, таким образом, я не знаю то, что еще я могу попытаться разблокировать свой экземпляр. Хостом является DigitalOcean, если это имеет значение.
Временное решение проблемы
Параметр $SIZE задаётся в мегабайтах и, теоретически, может быть любым числом, которое имеет смысл на конкретном компьютере. В нашем случае был использован параметр 8000, который, с учётом особенностей работы сервера, позволил выиграть достаточно времени на исследования. Кроме того, мы увеличили динамическую память. Мы пользуемся Heroku, там это делается просто.
Также мы воспользовались сервисом Twilio, настроили его так, чтобы нас оповещали каждый раз, когда на сервер приходит запрос, требующий особенно много памяти. Это позволило нам наблюдать за запросом и перезапускать сервер после его завершения. Такое решение неидеально, но для того, чтобы наши пользователи не сталкивались с отказами, мы были готовы на всё, даже на круглосуточные дежурства без выходных.
▍ Утечка памяти
В информатике утечка памяти — это разновидность неконтролируемого использования ресурсов, которая возникает, когда программа неправильно управляет выделением памяти, в результате чего память, которая больше не нужна, не освобождается.
В низкоуровневых языках вроде C утечки памяти часто возникают в ситуации, когда память выделяют, например так: buffer = malloc(num_items*sizeof(double)); , но не освобождают после того, как память больше не нужна: free(buffer); .
В языках с автоматическим управлением освобождением памяти утечки возникают, когда к сущностям, которые больше не нужны, можно получить доступ из исполняющейся программы, или из некоего корневого объекта. В случае с JavaScript, любой объект, к которому можно обратиться из программы, не уничтожается сборщиком мусора, соответственно, место, которое он занимает в куче, не освобождается. Если размер кучи вырастет слишком сильно, возникнет ситуация нехватки памяти.
Отладка
Итак, благодаря настройкам Node и организации мониторинга сервера мы выиграли время, которое можно было потратить на то, чтобы дойти до первопричины неполадки. На первый взгляд может показаться, что «проблема с памятью сервера» — это нечто ужасное, а для избавления от этой «проблемы» потребуются фантастические инструменты и умения. Однако, на самом деле, всё не так уж и страшно. Есть вполне доступные инструменты для исследования приложений, существует множество материалов, в которых можно найти подсказки. Мы, для исследования памяти Node-сервера, будем пользоваться инструментами разработчика Chrome.
3 ответа
Я бы посоветовал вам перезагрузить дроплет (просто зайдите в панель управления клиента и выберите «Перезагрузить»), ssh , а затем запустите top или htop . Следите за использованием памяти и посмотрите, какой процесс использует всю память. Оттуда попробуйте либо
-
Убить / удалить неисправную программу / процесс
2 Answers 2
The error is caused by the PID 1 process exits in the new namespace.
After bash start to run, bash will fork several new sub-processes to do somethings. If you run unshare without -f, bash will have the same pid as the current "unshare" process. The current "unshare" process call the unshare systemcall, create a new pid namespace, but the current "unshare" process is not in the new pid namespace. It is the desired behavior of linux kernel: process A creates a new namespace, the process A itself won't be put into the new namespace, only the sub-processes of process A will be put into the new namespace. So when you run:
The unshare process will exec /bin/bash, and /bin/bash forks several sub-processes, the first sub-process of bash will become PID 1 of the new namespace, and the subprocess will exit after it completes its job. So the PID 1 of the new namespace exits.
The PID 1 process has a special function: it should become all the orphan processes' parent process. If PID 1 process in the root namespace exits, kernel will panic. If PID 1 process in a sub namespace exits, linux kernel will call the disable_pid_allocation function, which will clean the PIDNS_HASH_ADDING flag in that namespace. When linux kernel create a new process, kernel will call alloc_pid function to allocate a PID in a namespace, and if the PIDNS_HASH_ADDING flag is not set, alloc_pid function will return a -ENOMEM error. That's why you got the "Cannot allocate memory" error.
You can resolve this issue by use the '-f' option:
If you run unshare with '-f' option, unshare will fork a new process after it create the new pid namespace. And run /bin/bash in the new process. The new process will be the pid 1 of the new pid namespace. Then bash will also fork several sub-processes to do some jobs. As bash itself is the pid 1 of the new pid namespace, its sub-processes can exit without any problem.
Что творится с серваком? Несколько лет работал а тут такое. Раза с 20 зашел по ssh на все команды fork: Cannot allocate memory, но если долго пытаться то команды выполняются. Свободной памяти много. В чем проблема? Может быть в физическом повреждении RAM?
OS, ядро, dmesg, сколько процессов ? Может баг в ядре который ребутом полечится
А процессов сколько?
Debian 7.11 3.2.0-4-amd64 процессов 146 в dmesg чисто, ребут был.
/proc/meminfo и /proc/sys/vm/overcommit_memory покажи
3.2.0 - както стремно (уже 84 багфикса было для 3.2 ветки).
А что в /proc/slabinfo ? И сколько всего потоков ?
у тебя что-то из лимитных вещей закончилось. Возможно дескрипторы или что-то подобное.
Dark_SavanT ★★★★★ ( 13.02.17 20:41:47 )
Последнее исправление: Dark_SavanT 13.02.17 20:42:03 (всего исправлений: 1)
Окей, а теперь покажи пожалуйста ulimit -a
Хм, тоже вроде никакого криминала(у меня например, некоторые параметры даже ниже по дефолту). Ну и наконец выхлоп ps aux на какой-нибудь pastebin бы не помешал
Update: вот тут чуть подробнее расписали возможные проблемы
Pinkbyte ★★★★★ ( 13.02.17 21:02:13 )
Последнее исправление: Pinkbyte 13.02.17 21:05:19 (всего исправлений: 1)
Ищите процесс (процессы) которые запросили большое количество RAM (можно в top Shift+M и смотреть у кого большой VIRT)
Вообще не интересно самый жирный это
И кто у нас 21776? Чинится ли всё, если его прибить?
Насколько я понял 21776 процесс запросил 36G RAM
Да действительно прибил 21776 и все наладилось. Но вот что странно запросил он 35.0g а использовал всего 2.5g. Притом своп пустой на запросы памяти сыпется Cannot allocate memory. Почему?
Есть подозрение что дело в overcommit и бажном процессе, который сделал malloc на overдохрена памяти
top - 21:32:03 up 5:36, 2 users, load average: 0.14, 0.19, 0.18
Tasks: 138 total, 1 running, 137 sleeping, 0 stopped, 0 zombie
%Cpu(s): 13.5 us, 0.8 sy, 0.0 ni, 85.3 id, 0.2 wa, 0.0 hi, 0.1 si, 0.0 st
KiB Mem: 32878740 total, 10601464 used, 22277276 free, 62572 buffers
KiB Swap: 16768892 total, 0 used, 16768892 free, 6246996 cached
Это ты шифруешься так, что ли? Я понимаю там логины пользователей еще скрывать, но что у тебя такого сверхсекретного в именах процессов? :-)
И еще, ты так и не ответил что именно за процесс был под pid 21776.
Логично. Процесс кривой но нужный, раньше столько МЕМа не заказывал.
Это что бы холивар не разводить. Java это была java :)))
Не дай бохъ узнают, шо java (подкодит по кол-ву символов) крутит. ;)
Вариантов тут немного: либо фиксить поведение процесса(патчить, писать багрепорты и/или накатывать новую версию), либо переключать overcommit в режим 2.
ОСТОРОЖНО: неправильные настройки overcommit могут к чертям сломать тебе систему, пока не откатишь в зад. Например, у меня при дефолтных 50% overcommit_ratio на десктопе с 4G RAM напрочь отказывались запускаться ЛЮБЫЕ приложения на java(даже hello world).
Update: гы, как в воду глядел, начал писать коммент до того как увидел инфу про java :)
Крути настройки GC в java, ну или overcommit, но осторожно и желательно с локальным доступом(хотя SSH по идее прибивается OOM-Killer-ом в сааамую последнюю очередь, так что. )
Pinkbyte ★★★★★ ( 13.02.17 21:48:46 )
Последнее исправление: Pinkbyte 13.02.17 21:49:58 (всего исправлений: 2)
Можно ли что-то сделать исключительно встроенными командами bash?
Частный случай: можно ли в пустом bash изобразить аналоги cat и kill? ( желательно ещё ls, но его кое-как можно заменить автодополнением по табу )
З.Ы. не linux. aix
builtin kill $pid
man proc
/proc/sysrq-trigger например
Ты можешь попробовать «exec kill . ». Но
- возможно памяти не хватит даже на exec и получится EPIC FAIL,
- возможно это прокатит всего один раз и второй раз ты зайти вообще не сможешь, так что целиться kill'ом надо хорошо
это пакет с отдельными утилитами, на запуск которых не хватит памяти
ну я как бы знаю про неё. Именно поэтому мне нужны аналоги cat и kill на чистом bash, а процесс я и сам в /proc найду
hmc, например. перезагрузить не проблема
ребут не вариант?
болезный, прочитай как переводится built-in
блин, смотрю в монитор и вижу «binutils». Перерыв нужен
Смутно помню, что был такой вопрос на яндекс олимпиаде. Нашёл
11. На сервере запустили форк-бомбу. У Вас есть открытая ssh-сессия на машину. Серверу в настоящий момент настолько плохо, что нельзя даже запустить ps, так как закончились pid-ы. Родительский и дочерние процессы форк-бомбы называются someprogram.bin Каким образом можно убить все процессы someprogram.bin?
Ответ:
exec busybox/python, откуда в цикле убить все процессы не порождая новых процессов.
к сожалению, питона и busybox нет. Можно запустить perl, но работать с ним интерактивно я не умею.
▍ Снепшот кучи
«Утечка памяти» — это проблема, которая выражается в постоянно растущем размере кучи. В результате куча оказывается слишком большой для продолжения нормальной работы сервера. Поэтому в самом начале исследования нужно сделать несколько снепшотов (снимков состояния) кучи, с некоторым интервалом, и погрузиться в исследование этих снепшотов с использованием инструментов разработчика Chrome для того, чтобы понять, почему куча так велика и почему она растёт. Обратите внимание на то, что следует делать несколько снепшотов, через некоторое время, в результате можно будет изучить объекты, которые будут переходить из одного снепшота в другой. Эти объекты, вполне возможно, являются виновниками утечки памяти. Существует множество способов создать снепшот кучи.
Итоги
Две вышеописанные проблемы с памятью заставили нас притормозить развитие нашего проекта, которое до этого шло очень быстро, и проанализировать производительность сервера. Теперь мы понимаем особенности производительности сервера на гораздо более глубоком уровне, чем раньше, и мы знаем, сколько времени нужно для нормального выполнения отдельных функций, и сколько памяти они используют. У нас появилось гораздо лучшее понимание того, какие ресурсы нам нужны при дальнейшем масштабировании проекта. И, что самое важное, мы перестали бояться проблем с памятью и перестали ожидать их появления в будущем.
I'm experimenting with linux namespaces. Specifically the pid namespace.
I thought I'd test something out with bash but run into this problem:
Running ls from there gave a core dump. Exit is the only thing possible.
Why is it doing that?
▍ Использование heapdump для создания снепшотов кучи
Мы, для создания снимков кучи, пользовались heapdump. Этот npm-пакет оказался весьма полезным. Его можно импортировать в код и обращаться к нему в тех местах программы, где нужно делать снепшоты. Например, мы делали снепшот каждый раз, когда сервер получал запрос, который мог вызвать процесс, интенсивно использующий память. Тут же мы формировали имя файла, содержащее текущее время. Таким образом мы могли воспроизводить проблему, отправляя на сервер всё новые и новые запросы. Вот как это выглядит в коде:
Выявление проблем с памятью
Признаки утечки памяти, кроме того, включают в себя уменьшение производительности программы с течением времени. Если сервер периодически выполняет один и тот же процесс, который изначально быстр, а перед отказом постепенно становится медленнее, это, весьма вероятно, говорит об утечке памяти.
Признаки чрезмерного использования памяти обычно выражаются в низкой производительности программ. Однако, чрезмерное использование памяти без утечки со временем не приводит к падению производительности.
Загрузка снепшотов и определение типа проблемы с памятью
Следующий шаг заключается в загрузке снепшотов на закладке Memory (память) инструментов разработчика Chrome. Если вы использовали для создания снепшотов кучи удалённый отладчик Chrome, то они уже будут загружены. Если вы использовали heapdump, то вам понадобится загрузить их самостоятельно. Обязательно загружайте их в правильном порядке, а именно — в том, в котором они были сделаны.
Самое главное, на что надо обращать внимание на данном этапе работы, заключатся в том, чтобы понять — с чем именно вы столкнулись — с утечкой или с чрезмерным использованием памяти. Если перед вами утечка памяти, то вы, вероятно, уже получили достаточно данных для того, чтобы начать исследовать кучу в поисках источника проблемы. Однако, если перед вами — чрезмерное использование памяти, вам нужно попробовать некоторые другие методы анализа для того, чтобы получить содержательные данные.
Наша первая проблема с памятью выглядела, на закладке Memory инструментов разработчика Chrome, так, как показано ниже. Несложно заметить, что куча постоянно растёт. Это говорит об утечке памяти.
Куча увеличивается со временем — очевидная утечка памяти
Наша вторая проблема с памятью, которая возникла через пару месяцев после исправления утечки, в итоге, на тех же испытаниях, выглядела так, как показано на рисунке ниже.
Куча со временем не растёт — это не утечка памяти
Размер кучи со временем не меняется. Всё дело в том, что при чрезмерном использовании памяти её размер превышает некие ожидаемые показатели не всегда, а лишь при выполнении определённых операций. При этом снепшоты делаются в какие-то моменты, которые никак не привязаны к ситуациям с чрезмерным использованием памяти. Если в момент создания снепшота не происходило выполнения неправильно написанной ресурсоёмкой функции, тогда куча не будет содержать никакой ценной информации о памяти, используемой этой функцией.
Для выявления подобных проблем мы рекомендуем два способа, которые помогли нам обнаружить виновников проблемы — функцию и переменную. Это — запись профиля выделения памяти и создание снепшотов на сервере, находящемся под серьёзной нагрузкой.
Если вы используете версию Node 6.3 или более позднюю, вы можете записать профиль выделения памяти через удалённый отладчик Chrome, запустив Node с уже упоминавшимся ключом --inspect . Это даст сведения о том, как отдельные функции используют память с течением времени.
Запись профиля выделения памяти
Ещё один вариант заключается в отправке множества одновременных запросов к вашему серверу и в создании множества снепшотов во время обработки этих запросов (предполагается, что сервер работает асинхронно, как результат, некоторые снепшоты могут оказаться гораздо больше других, что укажет на проблему). Мы бомбардировали сервер запросами и делали снепшоты. Некоторые из них оказались очень большими. Исследованием этих снепшотов можно заняться для выявления источника проблемы.
Предложения по предотвращению повторения проблемы
- Рекомендуется добавить память подкачки , поскольку она выделяет больше памяти, если у вас заканчивается.
- Каждый раз при установке программы, убедитесь, что вы настроили их правильно, чтобы они не работали непреднамеренно (например, занимали память)
- После каждого добавления пакета или настройки чего-то нового, проверьте с помощью htop или top , чтобы узнать, сколько памяти вы используете для текущих программ. Если вы заметили, что используете почти все, попробуйте очистить некоторые, пройдя и удалив ненужные программы / процессы.
- Если есть что-то, что запускается автоматически (кроме системных процессов, конечно!), вы не узнаете или не хотите, чтобы запускался автоматический, удалите его! Но всегда изучайте, что такое процесс, прежде чем его убить / удалить, так как он может быть важен для процедур загрузки или системных функций и т. Д.
В завершение принятого ответа следует учесть еще одну вещь: в вашей системе могут закончиться дескрипторов файлов или даже буферов сокетов и все еще есть много памяти, давая ту же ошибку. Это особенно верно, если виртуальный хостинг накладывает ограничения такого характера. В системах OpenVZ следите за содержимым
. Это даст вам в самом правом столбце первые переполнения. Если это правда, либо перейдите к более крупному пакету хостинга, либо найдите наиболее вероятного виновника: базу данных mysql или mariadb, которая может, при наличии дефектного приложения PHP, обрабатывать файлы утечки до сотен в секунду.
Это также может произойти, если на вашем веб-сервере есть ssh, открытый для Интернета, и он принимает входы по имени пользователя и паролю: даже если у вас запущен fail2ban, вы могли столкнуться с попыткой разбить распределенный словарь, что также потребляет много ресурсов.
Недавно в компании Reside Real Estate столкнулись с проблемами: в самые ответственные моменты начал падать Node.js-сервер. Подозрение пало на память. Сотрудники компании прибегли к временным мерам, что позволило избавить от неудобств пользователей, и занялись поисками источника проблем. В результате им удалось найти и устранить неполадки.
В этом материале они рассказывают о том, как искать и устранять ошибки, связанные с использованием памяти. А именно, речь пойдёт об утечках памяти, и о ситуациях, когда программы используют гораздо больше памяти, чем им на самом деле нужно. Этот рассказ поможет тем, кто столкнётся с чем-то похожим, сразу понять причину странного поведения сервера и быстро вернуть его в строй.
Анализ снепшотов
Теперь у нас есть данные, которые вполне могут помочь найти виновников проблем с памятью. В частности, рассмотрим анализ ситуации, в которой размеры последовательно сделанных снепшотов растут. Вот один из снепшотов, который загружен на вкладке Memory инструментов разработчика Chrome.
Исследование утечки памяти — все функции указывают на наш сервис электронной почты
Показатель Retained Size — это размер памяти, освобождённой после того, как объект удалён вместе со своими зависимыми объектами, которые недостижимы из корневого объекта.
Анализ можно начать с сортировки списка по убыванию по параметру Retained Size, после чего приступить к исследованию больших объектов. В нашем случае имена функций указали нам на ту часть кода, которая вызывала проблему.
Так как мы были уверены в том, что перед нами утечка памяти, мы знали, что исследование стоит начать с поиска переменных с неподходящей областью видимости. Мы открыли файл index.js почтовой службы и тут же обнаружили переменную уровня модуля в верхней части файла.
Мы со всем этим разобрались, внесли необходимые изменения, протестировали проект ещё несколько раз и исправили в итоге утечку памяти.
Вторую проблему отлаживать было сложнее, но тут сработал тот же подход. Ниже показан профиль выделения памяти, который мы записали с использованием инструментов разработчика Chrome и ключа Node --inspect .
Поиск виновников чрезмерного использования памяти
Так же как при анализе данных в ходе поиска утечки памяти, многие имена функций и объектов с первого взгляда узнать не удаётся, так как находятся они на более низком уровне, чем код, который пишут для Node.js. В подобной ситуации следует, встретив незнакомое имя, записать его.
Профиль выделения памяти привёл нас к одной из функций, recordFromSnapshot , она стала хорошей отправной точкой. Наше исследование снепшота кучи, которое не особенно отличалось от исследования, выполняемого при поиске утечки памяти, позволило обнаружить очень большой объект target . Это была переменная, объявленная внутри функции recordFromSnapshot . Эта переменная осталась от старой версии приложения, она была больше не нужна. Избавившись от неё, мы исправили ситуацию с чрезмерным использованием памяти и ускорили выполнение процесса, которое раньше занимало 40 секунд, до примерно 10 секунд. При этом процессу не требовалась дополнительная память.
▍ Использование удалённого отладчика Chrome для создания снепшотов кучи
Если вы работаете с Node 6.3. или с более поздней его версией, для создания снепшотов кучи можно использовать удалённый отладчик Chrome. Для того, чтобы это сделать, сначала запустите Node командой такого вида: node --inspect server.j s. Затем перейдите по адресу chrome://inspect . Теперь вы сможете удалённо отлаживать процессы Node. Чтобы сэкономить время, можете установить этот плагин Chrome, который автоматически откроет вкладку отладчика при запуске Node с флагом --inspect . После этого просто делайте снепшоты тогда, когда сочтёте это необходимым.
Средства удалённой отладки Chrome и создание снепшотов кучи
Типы проблем с памятью
▍ Чрезмерное использование памяти
В ситуации чрезмерного использования памяти программа занимает гораздо больше памяти, чем ей нужно для решения возложенной на неё задачи. Например, такое может возникнуть тогда, когда ссылки на большие объекты хранят дольше, чем нужно для правильной работы программы, что предотвращает уничтожение этих объектов сборщиком мусора. Подобное случается и тогда, когда в памяти держат большие объекты, которые попросту не нужны программе (это вызывает одну из двух основных проблем, которые мы рассмотрим ниже).
Читайте также: