Core dump — это снимок памяти процесса в момент аварии. Для админов и девопсов это прямой билет к причине crash без угадываний. Но экосистема Linux изменилась: вместо старого привычного файла core в текущем каталоге всё чаще работает systemd-coredump, пишет сжатые дампы в отдельное хранилище и управляет квотами. В статье — практическое руководство по включению и использованию coredump: от ulimit и core_pattern до gdb, дебаг-символов и правил очистки.
Зачем вам core dump в проде
Логи не всегда помогут: при падении из-за гонки потоков, переполнения стека или ошибочного доступа к памяти вы увидите лишь обрывочные сообщения. coredump фиксирует полный контекст: стек всех потоков, регистры, маппинги памяти, аргументы, иногда содержимое строк и структур. Это позволяет в gdb увидеть реальный backtrace и быстро локализовать проблему в коде или в сторонней библиотеке.
Правильно настроенный systemd-coredump не превращает диск в помойку: он умеет сжимать дампы, ограничивать размер, держать свободное место, а при необходимости можно писать дампы в каталог проекта с понятным шаблоном имени через core_pattern.
Как ядро решает, писать ли core dump
На запись дампа влияют несколько факторов:
- Лимит 
RLIMIT_COREпроцесса (управляется черезulimit -cилиprlimit). - Глобальная политика 
kernel.core_pattern— куда и как писать дампы (в файл или в пайпsystemd-coredump). - Флаг 
fs.suid_dumpable— что делать с setuid/setgid процессами и безопасностью их дампов. - Права на директорию назначения, свободное место и квоты 
systemd-coredump. 
Быстрая диагностика текущих настроек
Проверьте, куда вообще пойдёт дамп и разрешён ли он для вашего процесса:
# Текущий лимит ядра для core (0 — запрещено, unlimited — без лимита)
ulimit -c
# Все лимиты текущей оболочки (строка core file size)
ulimit -a
# Лимиты конкретного PID (например, оболочки)
prlimit -p $$
# Настройка ядра: шаблон пути или пайп
sysctl kernel.core_pattern
# Политика для SUID процессов (0 — запрет, 1 — ядро, 2 — в CWD)
sysctl fs.suid_dumpable
Если kernel.core_pattern начинается с вертикальной черты, например |/usr/lib/systemd/systemd-coredump %P %u %g %s %t %e, значит включён systemd-coredump. Если там путь с %-плейсхолдерами (например, /var/lib/coredumps/core.%e.%p.%t) — дампы будут писаться как файлы по этому шаблону.
systemd-coredump: как он работает и где лежат файлы
systemd-coredump перехватывает дампы через пайп из kernel.core_pattern, сжимает их и складывает в хранилище, обычно в /var/lib/systemd/coredump, а метаданные пишет в журнал (journald). Доступ к списку и выгрузке обеспечивается командой coredumpctl. По умолчанию ядро современных Debian/Ubuntu и многих других систем уже настроено на такой режим.
Сильные стороны этого подхода: единая точка настроек, автоматическая ротация по дисковым квотам и возможность быстро открыть дамп в gdb без ручных путей. Слабые стороны: не всем удобно, что файлы не лежат рядом с бинарём, и для контейнеров такой режим иногда не подходит (ниже об этом).
Ключевые параметры в coredump.conf
Основной файл настроек: /etc/systemd/coredump.conf (глобально) и /etc/systemd/coredump.conf.d/*.conf (дроп-ин конфигурации). Типичные параметры:
Storage=external|journal|none|both— где хранить содержимое дампа. Обычноexternal(в каталог) плюс метаданные в журнале.ProcessSizeMax=— максимальный размер дампа для одного процесса.ExternalSizeMax=— предел размера для «external» хранения.MaxUse=— общий лимит дискового пространства под дампы.KeepFree=— сколько места оставлять свободным на разделе.
Пример аккуратной политики на продакшене:
[Coredump]
Storage=external
ProcessSizeMax=2G
ExternalSizeMax=2G
MaxUse=8G
KeepFree=2G
После изменения перезапустите сервис обработки дампов:
systemctl restart systemd-coredump
Проверить, что всё работает, можно так:
coredumpctl list
coredumpctl info
coredumpctl gdb

Политики очистки и квоты
Когда достигаются лимиты MaxUse или KeepFree, старые файлы в /var/lib/systemd/coredump удаляются автоматически. Метаданные в журнале можно дополнительно чистить через политику самого journald. Вручную удалять файлы из каталога допустимо, но лучше полагаться на встроенную ротацию и корректные квоты — это безопаснее и воспроизводимее.
Включаем core dump для юзера, сервиса и всего хоста
Главный источник путаницы — разные уровни, где можно включить/выключить coredump.
Для интерактивной сессии (временный дебаг)
Если нужно поймать дамп от процесса, запущенного из вашей оболочки:
# Разрешить дампы в текущей оболочке
ulimit -c unlimited
# Запустить проблемную программу и дождаться падения
./myapp --debug
Этот способ не влияет на системные сервисы и пропадёт при выходе из shell. Подходит для локальной отладки или воспроизведения бага.
Для системного сервиса systemd
Процессы под управлением systemd берут лимиты из юнита. Добавьте в юнит LimitCORE или настройте по умолчанию:
# Дроп-ин для сервиса, создаёт файл override.conf
systemctl edit myapp.service
[Service]
LimitCORE=infinity
# Применить изменения
systemctl daemon-reload
systemctl restart myapp.service
Аналогично можно задать глобально для всех юнитов в /etc/systemd/system.conf:
# Включить ядровые дампы по умолчанию для сервисов (осторожно)
DefaultLimitCORE=infinity
Перезапустите PID 1 или перезагрузите хост для применения глобального значения. Вариант с дроп-ином на конкретный сервис безопаснее.
Если у вас воркеры и очереди под systemd, посмотрите конфигурационные подходы из материала как запускать и мониторить воркеры под systemd — те же принципы применимы к лимитам и логике перезапуска.
Через PAM и /etc/security/limits.conf
Для пользовательских сессий, создаваемых через PAM, лимиты можно задать в /etc/security/limits.conf:
# Пример: всем пользователям разрешить дампы
* soft core unlimited
* hard core unlimited
Но учтите: для сервисов systemd этот файл часто не применяется — используйте LimitCORE в юните.
Специфика отдельных сервисов
- PHP-FPM: помимо 
LimitCOREв юните, включите лимит в пуле:rlimit_core = unlimitedвphp-fpm.confили пуле. Перезапустите сервис. - Nginx: можно указать 
worker_rlimit_coreиworking_directory, если пишете в файлы поcore_pattern. Сsystemd-coredumpдостаточноLimitCOREв юните. - Java: 
coredump— это дамп JVM-процесса. Полезно сохранить ещё иhs_err_pid*.log. Пакеты дебага для JVM помогут вgdb. - Go/Node.js: 
gdbпокажет стек нативных библиотек и рантайма; чем больше символов, тем лучше. Для Go иногда помогает флаг компиляции без агрессивной оптимизации. 
Альтернатива: писать core в директорию по core_pattern
Если по организационным причинам удобнее иметь файлы рядом с артефактами релиза, можно отключить пайп в systemd-coredump и задать путь. Например:
# Писать файлы в /var/coredumps с понятным шаблоном
sysctl kernel.core_pattern=/var/coredumps/core.%e.%p.%t
# Включить PID в имя (дополнительно)
sysctl kernel.core_uses_pid=1
Создайте каталог и права заранее, сервисам нужны права на запись. Минусы подхода: нет автоматических квот и сжатия, придётся делать ротацию самостоятельно (tmpfiles.d, cron, logrotate или ansible-роль). На продакшене чаще удобнее управляться через systemd-coredump.
Работа с дампами: coredumpctl и gdb
После падения проверьте список доступных дампов:
coredumpctl list
# Подробности по последнему дампу
coredumpctl info
# Выгрузить в файл для передачи разработчикам
coredumpctl dump -o /tmp/last.core
# Открыть сразу в gdb (если есть бинарь и символы)
coredumpctl gdb
Если вы писали в файлы по core_pattern, запускайте gdb так:
# Бинарь и core-файл
gdb -q /opt/myapp/bin/myapp /var/coredumps/core.myapp.12345.1716280000
# Базовый набор команд в gdb
bt
bt full
thread apply all bt
Минимальный чек-лист в gdb
info threads— какие потоки были живы.thread apply all bt— стек каждого потока.bt full— стек активного потока с локальными переменными.frame N— перейти к интересующему фрейму.info registers— регистры, полезно при SIGSEGV.p some_varилиp/x ptr— посмотреть значение/указатель.info sharedlibrary— загруженные so и есть ли символы.set pagination off— удобнее читать длинные бэктрейсы.
Символы и debuginfo
Без символов (debug symbols) бэктрейс получится «голым» — адреса вместо имён. Решение — поставить пакеты с символами для самого бинаря и зависимостей. На RPM-базе это обычно -debuginfo пакеты, на DEB — -dbgsym. Если у вас собственные артефакты, собирайте с -g и отделяйте символы в .debug файлы, а в релизный бинарь оставляйте build-id: тогда gdb подтянет символы автоматически по build-id, если положить их в стандартные директории (.build-id дерево) или указать dir/set debug-file-directory в gdb.
Ещё нюансы:
- Оптимизация компилятора (
-O2/-O3) делает бэктрейсы менее «линейными», переменные могут быть оптимизированы. Для воспроизведения сложных багов старайтесь иметь сборку с умеренной оптимизацией или отдельный релиз с символами. - Для многих интерпретируемых рантаймов (JVM, Python) дамп нативной памяти помогает лишь частично; ищите их собственные артефакты крашей параллельно.
 

Контейнеры и неймспейсы: подводные камни
В контейнерах PID 1 часто не systemd, а лёгкий init или сам процесс приложения. Это означает:
systemd-coredumpобычно недоступен внутри контейнера, аkernel.core_patternуправляется на уровне хоста.- Дампы будут пытаться писаться в файловую систему контейнера (часто tmpfs/overlay) и пропадут при пересоздании. Лучше монтировать внешний каталог для дампов или использовать хостовый 
systemd-coredump. - Проверьте 
ulimit -cв контейнере и параметр--ulimitна уровне оркестратора, чтобы процесс мог писать дампы. 
На общем хостинге и в некоторых PaaS функции дампов могут быть ограничены. Для воспроизводимой отладки удобнее поднять отдельный стенд на VDS, где вы полностью контролируете ядровые лимиты и политику хранения.
Безопасность: секреты в памяти
Дамп памяти содержит приватные ключи, токены, пароли и пользовательские данные. Обращайтесь с ним как с чувствительным артефактом:
- Ограничьте доступ к каталогу дампов правами файловой системы.
 - Не копируйте дампы на внешние ресурсы без шифрования.
 - Настройте 
fs.suid_dumpable=0на бою, если нет сценария, где нужны дампы от SUID. - Ограничьте размеры в 
coredump.conf, чтобы не рисковать исчерпанием диска. 
Золотое правило: сначала политика (лимиты, квоты, места хранения), потом отладка. И только самым доверенным людям доступ к полным дампам.
Если вы укрепляете сервисы под systemd, пригодятся техники из статьи sandbox и hardening для systemd сервисов — это напрямую помогает снизить риск утечек через дампы.
Частые проблемы и как их лечить
- Дамп не создаётся. Проверьте 
ulimit -c,LimitCORE, права записи в каталог, значениеkernel.core_patternи наличие свободного места. Посмотрите логиsystemd-coredumpиjournald. - Создаётся пустой или очень маленький файл. Вероятно, лимит 
ProcessSizeMaxилиExternalSizeMax. Поднимите значения. - Нет символов в 
gdb. Установите-debuginfo/-dbgsym, проверьтеbuild-id, путь к.debugфайлам иinfo sharedlibrary. - Не тот бинарь в 
gdb. Если бинарь к моменту разбора уже обновился, создайте копию соответствующей версии или используйтеcoredumpctl gdb, который найдёт версию из метаданных, если доступна. - Контейнеры не пишут дампы. Проверьте ulimit в оркестраторе и смонтируйте каталог для дампов. Убедитесь, что хост не перенаправляет дампы в 
systemd-coredumpбез доступа из контейнера. 
Шаблоны и практические пресеты
Минимальный пресет для продакшена с systemd-coredump
# /etc/systemd/coredump.conf.d/10-prod.conf
[Coredump]
Storage=external
ProcessSizeMax=2G
ExternalSizeMax=2G
MaxUse=8G
KeepFree=2G
# В сервисе, где нужен дамп (пример)
# systemctl edit myapp.service
[Service]
LimitCORE=infinity
Пресет для локальной отладки в каталоге проекта
# Писать рядом с артефактами
mkdir -p /var/coredumps
chmod 750 /var/coredumps
sysctl kernel.core_pattern=/var/coredumps/core.%e.%p.%t
sysctl kernel.core_uses_pid=1
# В shell
ulimit -c unlimited
Шпаргалка команд
# Проверить настройки
ulimit -c
ulimit -a
prlimit -p $$
sysctl kernel.core_pattern
sysctl fs.suid_dumpable
# Управление systemd-coredump
systemctl restart systemd-coredump
coredumpctl list
coredumpctl info
coredumpctl dump -o /tmp/last.core
coredumpctl gdb
# Базовый gdb
gdb -q /path/to/bin /path/to/core
thread apply all bt
bt full
info registers
info sharedlibrary
Итог
Чтобы извлечь максимум из coredump и не навредить продакшену: включайте дампы адресно в нужных сервисах (LimitCORE), держите аккуратные квоты в coredump.conf, следите за безопасностью и хранением, и обязательно готовьте символы для gdb. С таким сетапом вы превращаете случайный crash в конкретный отчёт с бэктрейсами и координатами бага.
                            

