Если что-то не работает
Приложение падает с Killed или exit code 137: не хватает памяти
Коротко
Слово Killed в логах или код завершения 137 почти всегда означают, что приложение превысило доступную память и система принудительно его остановила. Код 137 складывается из 128 и номера сигнала 9, SIGKILL: процесс не завершился сам, его убили, поэтому сообщения об ошибке в логах обычно нет. Чаще всего память съедают модель нейросети, большой файл, целиком загруженный в pandas, браузер для Selenium или список, который растёт без конца. Сначала стоит уменьшить аппетит кода, а если приложение тяжёлое по своей природе, нужен тариф с большим объёмом памяти.
- Код завершения 137 равен 128 плюс 9: процесс остановлен сигналом SIGKILL, чаще всего из-за превышения лимита памяти.
- Когда приложение убивают за нехватку памяти, Python не успевает напечатать трейсбек, поэтому в логах остаётся только Killed или вообще ничего.
- Файл CSV в pandas занимает в памяти заметно больше, чем на диске, поэтому большие файлы читают частями через параметр chunksize.
- Ошибка JavaScript heap out of memory в Node.js — это внутренний лимит движка V8, а не лимит сервера, и лечится она иначе, чем код 137.
- Если в docker-compose несколько сервисов, они делят между собой одну и ту же память тарифа.
Приложение запускается, немного работает и внезапно пропадает. В логах последняя строка — Killed, или проект завершился с кодом 137, или сообщений нет вовсе: только что всё печаталось, и вдруг тишина. Иногда это повторяется по кругу: приложение перезапускается, доходит до того же места и снова исчезает. Ошибки в коде при этом может и не быть — он делает ровно то, что написано, просто для этого нужно больше памяти, чем есть.
У каждого приложения на сервере есть потолок памяти. Когда процесс пытается взять больше, система не ждёт и не спрашивает: она останавливает его сигналом SIGKILL, от которого нельзя ни защититься, ни красиво завершиться. Отсюда и код 137, и отсутствие трейсбека. По-английски это называют OOM, out of memory. Ниже — как найти, что именно съедает память, и как это исправить.
| Что ест память | Как это выглядит | Что сделать |
|---|---|---|
| Модель нейросети (torch, transformers) | падает сразу при запуске или на первом запросе | взять модель поменьше, загружать её один раз при старте или вызывать модель через API |
| Большой файл в pandas | падает на чтении файла | читать частями через chunksize, брать только нужные колонки через usecols, задать dtype |
| Selenium или Playwright с Chrome | падает через несколько страниц | режим headless, один браузер на весь скрипт, закрывать страницы и вызывать driver.quit() |
| Утечка в цикле | работает часами, потом падает, и так по кругу | ограничить кэши и списки, закрывать соединения и файлы, не копить историю в памяти |
| Картинки и видео | падает на больших загрузках | уменьшать изображение до обработки, обрабатывать файлы по одному, сохранять на диск |
| Сборка фронтенда, Rust или Java | падает на этапе сборки, а не при работе | собрать фронтенд у себя и загрузить готовую папку; для Rust уменьшить параллельность сборки |
| Несколько сервисов в docker-compose | падает самый прожорливый сервис | убрать лишние сервисы или вынести базу во внешний сервис |
Убедитесь, что дело в памяти#
Посмотрите, когда именно падает приложение. Если сразу на старте — подозревайте загрузку модели, большого файла или тяжёлой библиотеки. Если через часы работы, а график памяти перед этим ровно растёт — это утечка. Код 137 бывает и по другой причине: например, когда запущен не тот файл и его останавливают принудительно, поэтому сверьте, что стартует именно ваше приложение, а не вспомогательный скрипт вроде init_db.py.
Найдите, что занимает больше всего#
Запустите приложение у себя и посмотрите, сколько памяти оно берёт, в диспетчере задач или командой вроде top. В Python помогает встроенный модуль tracemalloc: он показывает строки кода, на которых выделено больше всего памяти. Часто виновник находится за минуты — это одна строка, которая читает весь файл, создаёт модель или складывает результаты в список. Чинить имеет смысл именно её, а не всё приложение.
Обрабатывайте данные частями#
Большие файлы не нужно загружать целиком. В pandas у read_csv есть параметр chunksize — файл читается кусками, и в памяти одновременно лежит только один кусок; параметр usecols оставляет только нужные колонки. Ответы от API и выгрузки из базы тоже лучше обрабатывать постранично, а результаты сразу записывать на диск или в базу, а не копить в списке. Обычно это одна правка, которая снижает потребление в разы.
Облегчите браузер и модели#
Если в проекте Selenium или Playwright, запускайте браузер в режиме headless, без окна, держите один экземпляр на весь скрипт и обязательно закрывайте его через driver.quit(): каждый забытый браузер продолжает держать память. С нейросетями правило похожее: загружайте модель один раз при старте, а не на каждый запрос, и выбирайте облегчённую версию. Если модель всё равно не помещается, проще обращаться к ней через API провайдера, чем держать её у себя.
Закройте утечки в долгоживущем коде#
Бот или скрипт, который работает сутками, падает по кругу, если что-то в нём растёт без ограничения: словарь с историей всех пользователей, кэш без предела, список обработанных сообщений, незакрытые соединения с базой. Ограничьте размер кэша, храните историю в базе, а не в памяти, и закрывайте файлы и соединения через with. После правки понаблюдайте за памятью несколько часов: она должна выйти на ровную линию, а не расти.
Если приложению правда нужно больше, возьмите тариф побольше#
Есть приложения, которым много памяти нужно по самой своей сути: модель, которую нельзя заменить, большой датасет, несколько сервисов рядом. Тогда экономия упирается в потолок, и правильное решение — тариф с большим объёмом памяти. Сколько памяти даёт каждый тариф, указано на странице тарифов. Падение на этапе сборки, а не при работе, — отдельный случай: его обычно лечат тем, что собирают проект заранее или уменьшают параллельность сборки.
Killed и exit code 137 — не загадочный сбой, а прямое сообщение: приложению не хватило памяти. В большинстве случаев хватает одной правки — читать файл частями, закрыть браузер, загружать модель один раз. В Netrun падение из-за памяти видно сразу: на странице проекта появляется сообщение, что приложению не хватило памяти, с указанием лимита, проект перезапускается сам, а логи и нагрузка видны в кабинете. Если приложение тяжёлое по своей природе, на тарифах Pro и Max памяти больше, а у проекта с docker-compose она делится между сервисами. Попробовать Netrun.
Частые вопросы
Что значит exit code 137?
Это код, с которым завершается процесс, остановленный сигналом SIGKILL: 128 плюс номер сигнала 9. Чаще всего такой сигнал посылает система, когда приложение превысило лимит памяти. Сам процесс в этот момент ничего не успевает записать, поэтому подробностей в логах обычно нет.
Почему локально всё работает, а на сервере падает?
На компьютере у приложения гигабайты свободной памяти, а на сервере у него свой фиксированный потолок. Код, который спокойно съедает пару гигабайт на ноутбуке, на сервере упирается в лимит и останавливается. Проверьте, сколько памяти приложение берёт у вас, и сравните с лимитом тарифа.
Можно ли поймать нехватку памяти в коде и обработать её?
Почти нет. Исключение MemoryError в Python возникает редко, потому что система обычно убивает процесс раньше, чем Python успевает его выбросить. Надёжнее заранее не допускать перерасхода: читать данные частями, ограничивать кэши и следить за памятью.
Что делать с ошибкой JavaScript heap out of memory?
Это внутренний лимит движка Node.js, он может сработать раньше, чем кончится память сервера. Его поднимают флагом --max-old-space-size, но значение должно оставаться ниже лимита памяти тарифа, иначе вместо этой ошибки вы получите код 137. Если ошибка возникает при сборке фронтенда, проще собрать проект у себя и загрузить готовую папку.
Поможет ли автоматический перезапуск?
Перезапуск вернёт приложение к работе, но если причина в утечке, оно снова упадёт через то же время. Это нормально как страховка, но не как решение. Если падения повторяются по кругу, ищите, что растёт в памяти, или переходите на тариф побольше.
Что будет, если приложение упадёт?
Мы следим за проектами и перезапускаем их при сбое. Статус и логи видны в кабинете сразу, а уведомление приходит, только если приложение так и не вернулось в работу в течение часа: из-за коротких перебоев мы вас не тревожим.
Где посмотреть логи и статус проекта?
На странице проекта есть статус, логи и история событий — по ним видно, что происходит с проектом прямо сейчас. Лента логов показывает и более ранние строки: пролистайте её вверх, и они подгрузятся сами.
Чем отличается тариф Pro?
На тарифе Pro проект работает круглосуточно: сайт не засыпает и отвечает мгновенно, без паузы на пробуждение, а бот или фоновый скрипт работает постоянно, без ограничения по времени. Кроме того, на Pro больше памяти, процессора и места, а к сайту можно подключить свои домены — столько, сколько нужно, каждый с HTTPS.