Когда программа падает с сигналом сегментации, стандартный журнал часто ограничивается строкой о сбое и кодом возврата. Этого мало: нужен стек вызовов, значения переменных и состояние потоков. В системах с systemd сбор дампов памяти берёт на себя systemd-coredump: ядро передаёт ему сбойный процесс, утилита сохраняет дамп, а coredumpctl позволяет найти его и открыть в отладчике. Ниже — как проверить, что механизм работает, разобрать падение и не превратить дампы в утечку секретов.

Как ядро передаёт дамп в systemd

За передачу отвечает параметр ядра kernel.core_pattern. В типовой конфигурации systemd он указывает на обработчик:

sysctl kernel.core_pattern
# kernel.core_pattern = |/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h

Символ | означает, что ядро не пишет файл само, а запускает программу и передаёт дамп через стандартный ввод. Обработчик сжимает данные, складывает их в /var/lib/systemd/coredump и добавляет запись в журнал. Поэтому искать дампы нужно не в текущем каталоге, а через coredumpctl. Если в core_pattern стоит просто core или путь без обработчика, система настроена иначе — возможно, дампы пишутся в файл или отключены.

Проверим готовность механизма и текущий лимит размера дампа в оболочке:

systemctl status systemd-coredump.socket --no-pager
ulimit -c
cat /proc/sys/kernel/core_uses_pid

ulimit -c равный 0 запрещает создание дампа для процессов, запущенных из этой оболочки. Для сервисов действует свой лимит, заданный в unit-файле, поэтому настройка оболочки и настройка службы могут отличаться.

Проверка на учебном падении

Соберём небольшую программу с отладочной информацией и намеренно разыменуем нулевой указатель:

cat > /tmp/crash.c <<'EOF'
#include <stdio.h>
int main(void) {
    int *p = NULL;
    printf("before crash\n");
    *p = 42;
    return 0;
}
EOF
gcc -g -O0 -o /tmp/crash /tmp/crash.c
/tmp/crash; echo "exit=$?"

После падения смотрим список дампов. Запись должна появиться в течение нескольких секунд: обработчик работает асинхронно.

coredumpctl list --no-pager | tail -5
coredumpctl info --no-pager | head -40

coredumpctl info показывает сигнал, исполняемый файл, командную строку, идентификаторы процесса и пользователя, а также время события. Этого достаточно, чтобы понять, какой именно экземпляр упал. Если дампов много, фильтруйте по имени программы или времени: coredumpctl list /usr/bin/myapp --since today. Без root видны только дампы своего пользователя, поэтому системные службы разбирайте через sudo.

Разбор в gdb

Самый быстрый путь — попросить coredumpctl запустить отладчик для последнего дампа:

coredumpctl debug
# в gdb:
# bt
# bt full
# thread apply all bt
# info locals

Команда bt full печатает не только стек, но и аргументы и локальные переменные кадров. thread apply all bt обязателен для многопоточных программ: часто падает не тот поток, который виден первым. Если дамп нужно передать коллеге или открыть позже, сохраните его в файл:

coredumpctl dump /tmp/crash --output /tmp/crash.core
gdb -batch -ex 'bt full' /tmp/crash /tmp/crash.core

Для системных библиотек без отладочных символов стек будет содержать только адреса. Установите пакеты символов для своей программы и библиотек, а в свежих дистрибутивах включите debuginfod: gdb сам скачает нужные файлы по идентификатору сборки. Переменная DEBUGINFOD_URLS должна указывать на сервер вашего дистрибутива; конкретный адрес смотрите в документации. Без символов в стеке останутся в основном адреса, поэтому свою программу хотя бы собирайте с -g.

Настройка хранения и размера

Параметры задаются в /etc/systemd/coredump.conf и переопределяются файлами из /etc/systemd/coredump.conf.d/. Типовая настройка для сервера:

# /etc/systemd/coredump.conf.d/99-local.conf
[Coredump]
Storage=external
Compress=yes
ProcessSizeMax=2G
ExternalSizeMax=2G
MaxUse=4G
KeepFree=2G

Storage=external хранит файл дампа в каталоге, а запись о нём — в журнале, journal — только в журнале, none отключает сохранение. ProcessSizeMax ограничивает размер принимаемого дампа, ExternalSizeMax — размер сохраняемого файла. MaxUse и KeepFree защищают диск от заполнения: старые дампы удаляются автоматически. Настройки читаются при обработке очередного падения, перезапуск службы обычно не требуется, но проверить применение стоит на учебном примере.

Если дампы не нужны для конкретной службы, ограничьте размер в её unit-файле через drop-in:

systemctl edit myapp.service
[Service]
LimitCORE=0

Обратное тоже верно: если глобально стоит ulimit -c 0, а для службы нужен дамп, задайте LimitCORE=infinity и убедитесь, что core_pattern не переопределён. В контейнерах параметр core_pattern общий для хоста, поэтому дамп процесса из контейнера может оказаться на хосте; это стоит учитывать при разборе.

Если дампа нет

Проверьте состояние сокета и журнал обработчика. Если обработчик не запускается или завершается с ошибкой, дамп не сохранится, а причина попадёт в журнал. Также убедитесь, что каталог хранения доступен и на диске есть место: при срабатывании KeepFree старые записи удаляются, но новый дамп может не поместиться. Для службы с собственным LimitCORE=0 глобальные настройки не помогут.

journalctl -u systemd-coredump --since today --no-pager
df -h /var/lib/systemd/coredump
systemctl status systemd-coredump.socket --no-pager
systemctl list-units 'systemd-coredump@*' --no-pager

Ещё одна причина — падение в контейнере без доступа к хостовому обработчику или программа, которая перехватывает сигнал и завершается сама. В таких случаях смотрите код возврата и журнал приложения, а не только список дампов.

Очистка и безопасность

Дамп содержит память процесса: токены, пароли, персональные данные, фрагменты файлов. Не оставляйте их на общедоступных серверах дольше необходимого и ограничивайте доступ к каталогу. Для чувствительных служб разумно поставить Storage=none и собирать информацию другими способами. Чистка выполняется встроенными командами:

coredumpctl vacuum --vacuum-time=7d
coredumpctl vacuum --vacuum-size=1G
coredumpctl list --no-pager | wc -l

Файлы дампов сжаты, но это не делает их безопасными. Если дамп нужно передать разработчикам, лучше удалить из него очевидные секреты или использовать среду, где доступ к файлу ограничен. Также проверьте, не попадают ли дампы в резервные копии: каталог /var/lib/systemd/coredump часто исключают из бэкапа.

Итог

systemd-coredump превращает невнятное сообщение о падении в воспроизводимый материал для отладки. Проверьте core_pattern и лимиты, соберите программу с -g, найдите событие через coredumpctl list и откройте его в gdb. Настройте MaxUse и KeepFree, чтобы дампы не заняли диск, и помните о чувствительных данных внутри.

  • Механизм: core_pattern указывает на systemd-coredump, лимиты не нулевые.
  • Символы: программа и библиотеки имеют отладочную информацию.
  • Разбор: нужный дамп открывается, bt full читается.
  • Хранение: заданы MaxUse и KeepFree, старые записи удаляются.
  • Доступ: каталог дампов закрыт, секреты не попадают в резервные копии.

Если каждый пункт выполняется, разбор падения занимает минуты, а не часы.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте