Как сгенерировать дамп ядра в Linux при ошибке сегментации?

У меня есть процесс в Linux, в котором возникает ошибка сегментации. Как я могу сказать ему, что он генерирует дамп ядра, когда он терпит неудачу?

Как посмотреть дальше: stackoverflow.com/questions/8305866/…

Ciro Santilli TRUMP BAN IS BAD 14.04.2019 22:46
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
226
1
379 875
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

Ответ принят как подходящий

Это зависит от того, какую оболочку вы используете. Если вы используете bash, то команда ulimit управляет несколькими настройками, относящимися к выполнению программы, например, следует ли выгрузить дамп ядра. Если вы напечатаете

ulimit -c unlimited

тогда это скажет bash, что его программы могут выгружать ядра любого размера. Вы можете указать размер, например 52M, вместо неограниченного, если хотите, но на практике в этом нет необходимости, поскольку размер основных файлов, вероятно, никогда не будет для вас проблемой.

В tcsh вы должны ввести

limit coredumpsize unlimited

Извините, но это действительно ответ на ваш вопрос? вы спросили, как сгенерировать, но в нем говорится, как установить пределы

baye 09.08.2011 09:30

@lzprgmr: Чтобы уточнить: причина, по которой дампы ядра не создаются по умолчанию, заключается в том, что ограничение не установлено и / или установлено на 0, что предотвращает сброс ядра. Устанавливая неограниченный лимит, мы гарантируем, что дамп ядра всегда может быть сгенерирован.

Eli Courtwright 09.08.2011 16:30

Этот связь идет глубже и дает несколько дополнительных опций для включения генерации дампов ядра в Linux. Единственный недостаток в том, что некоторые команды / настройки остаются невыясненными.

Salsa 31.08.2011 23:45

В bash 4.1.2 (1) ограничения выпуска, такие как 52M, не могут быть указаны, что приводит к неверному числовому сообщению об ошибке. На странице руководства указано, что «Значения указаны с шагом 1024 байта».

a1an 11.09.2012 16:02

Ну, у меня был «маленький» проект OpenGL, который однажды сделал что-то странное и вызвал сбой X-сервера. Когда я вернулся, я увидел симпатичный маленький файл ядра на 17 ГБ (на разделе 25 ГБ). Определенно хорошая идея - ограничить размер основного файла :)

IceCool 08.09.2013 19:48

У меня вопрос. Я не хочу устанавливать свой безлимитный. Как я могу узнать, какой размер должен допускаться?

PolarisUser 22.08.2014 20:01

@PolarisUser: Если вы хотите убедиться, что ваш раздел не съедается, я рекомендую установить лимит примерно в 1 гиг. Он должен быть достаточно большим, чтобы обрабатывать любой разумный дамп ядра, при этом не угрожая израсходовать все оставшееся пространство на жестком диске.

Eli Courtwright 22.08.2014 20:51

Я хочу повторить установку лимита для coredumpsize, как человека, которому только что пришлось очистить пару сотен дампов ядра 20G.

JSybrandt 16.01.2018 21:50

внимание: он не сохраняется после выхода пользователя из системы, по крайней мере, в CentOS, вы должны отредактировать /etc/security/limits.conf, если хотите.

Imskull 29.01.2018 06:37

и не забудьте поместить это в .bashrc, чтобы вам не приходилось делать это все время.

BreakBadSP 14.01.2019 10:28

По умолчанию вы получите файл ядра. Убедитесь, что текущий каталог процесса доступен для записи, иначе основной файл не будет создан.

Под «текущим каталогом процесса» вы подразумеваете $ cwd на момент запуска процесса? ~ / abc> / usr / bin / cat def, если cat вылетает, текущий каталог, о котором идет речь, ~ / abc или / usr / bin?

Nathan Fellman 30.04.2009 11:52

~ / abc. Хм, комментарии должны быть длиной 15 символов!

Mark Harrison 01.05.2009 18:56

Это будет текущий каталог на момент SEGV. Кроме того, процессы, запущенные с другим эффективным пользователем и / или группой, отличным от реального пользователя / группы, не будут записывать файлы ядра.

Darron 26.01.2010 17:02

В конце я подключил gdb к процессу до его сбоя, а затем, когда он получил segfault, я выполнил команду generate-core-file. Это принудительное создание дампа ядра.

Как вы подключили GDB к процессу?

Chani 31.05.2013 08:03

Чтобы ответить Ritwik G, чтобы присоединить процесс к gdb, просто запустите gdb и введите 'attach 'где это номер pid процесса, который вы хотите присоединить.

Jean-Dominique Frattini 14.06.2013 00:47

(сокращенно ge)

user202729 24.06.2018 07:24

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

user202729 24.06.2018 07:25

Странно то, что я уже установил ulimit -c на unlimited, но файл ядра не создается, а файл generate-core-file в сеансе gdb действительно создает файл ядра, спасибо.

CodyChan 08.06.2020 13:54

Возможно, вы могли бы сделать это таким образом, эта программа является демонстрацией того, как перехватить ошибку сегментации, и передает оболочку отладчику (это исходный код, используемый в AIX) и печатает трассировку стека до точки ошибки сегментации. Вам нужно будет изменить переменную sprintf, чтобы использовать gdb в случае Linux.

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <stdarg.h>

static void signal_handler(int);
static void dumpstack(void);
static void cleanup(void);
void init_signals(void);
void panic(const char *, ...);

struct sigaction sigact;
char *progname;

int main(int argc, char **argv) {
    char *s;
    progname = *(argv);
    atexit(cleanup);
    init_signals();
    printf("About to seg fault by assigning zero to *s\n");
    *s = 0;
    sigemptyset(&sigact.sa_mask);
    return 0;
}

void init_signals(void) {
    sigact.sa_handler = signal_handler;
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigaction(SIGINT, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGSEGV);
    sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGBUS);
    sigaction(SIGBUS, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGQUIT);
    sigaction(SIGQUIT, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGHUP);
    sigaction(SIGHUP, &sigact, (struct sigaction *)NULL);

    sigaddset(&sigact.sa_mask, SIGKILL);
    sigaction(SIGKILL, &sigact, (struct sigaction *)NULL);
}

static void signal_handler(int sig) {
    if (sig == SIGHUP) panic("FATAL: Program hanged up\n");
    if (sig == SIGSEGV || sig == SIGBUS){
        dumpstack();
        panic("FATAL: %s Fault. Logged StackTrace\n", (sig == SIGSEGV) ? "Segmentation" : ((sig == SIGBUS) ? "Bus" : "Unknown"));
    }
    if (sig == SIGQUIT) panic("QUIT signal ended program\n");
    if (sig == SIGKILL) panic("KILL signal ended program\n");
    if (sig == SIGINT) ;
}

void panic(const char *fmt, ...) {
    char buf[50];
    va_list argptr;
    va_start(argptr, fmt);
    vsprintf(buf, fmt, argptr);
    va_end(argptr);
    fprintf(stderr, buf);
    exit(-1);
}

static void dumpstack(void) {
    /* Got this routine from http://www.whitefang.com/unix/faq_toc.html
    ** Section 6.5. Modified to redirect to file to prevent clutter
    */
    /* This needs to be changed... */
    char dbx[160];

    sprintf(dbx, "echo 'where\ndetach' | dbx -a %d > %s.dump", getpid(), progname);
    /* Change the dbx to gdb */

    system(dbx);
    return;
}

void cleanup(void) {
    sigemptyset(&sigact.sa_mask);
    /* Do any cleaning up chores here */
}

Возможно, вам придется дополнительно добавить параметр, чтобы gdb выгружал ядро, как показано здесь, в этом блоге здесь.

Есть еще кое-что, что может повлиять на создание дампа ядра. Я столкнулся с такими:

  • каталог для дампа должен быть доступен для записи. По умолчанию это текущий каталог процесса, но его можно изменить, установив /proc/sys/kernel/core_pattern.
  • в некоторых случаях значение ядра в /proc/sys/fs/suid_dumpable может препятствовать генерации ядра.

Есть и другие ситуации, которые могут помешать генерации, которые описаны на странице руководства - попробуйте man core.

Чтобы активировать дамп ядра, выполните следующие действия:

  1. В /etc/profile прокомментируйте строку:

    # ulimit -S -c 0 > /dev/null 2>&1
    
  2. В /etc/security/limits.conf закомментируйте строку:

    *               soft    core            0
    
  3. выполните cmd limit coredumpsize unlimited и проверьте его с помощью cmd limit:

    # limit coredumpsize unlimited
    # limit
    cputime      unlimited
    filesize     unlimited
    datasize     unlimited
    stacksize    10240 kbytes
    coredumpsize unlimited
    memoryuse    unlimited
    vmemoryuse   unlimited
    descriptors  1024
    memorylocked 32 kbytes
    maxproc      528383
    #
    
  4. чтобы проверить, записан ли основной файл, вы можете убить соответствующий процесс с помощью cmd kill -s SEGV <PID> (не требуется, на всякий случай, если не будет записан основной файл, это можно использовать в качестве проверки):

    # kill -s SEGV <PID>
    

После того, как corefile был записан, не забудьте снова деактивировать настройки coredump в соответствующих файлах (1./2./3.)!

Как объяснялось выше, настоящий вопрос, который задается здесь, заключается в том, как включить дампы ядра в системе, где они не включены. Здесь дан ответ на этот вопрос.

Если вы пришли сюда в надежде узнать, как сгенерировать дамп ядра для зависшего процесса, ответ будет

gcore <pid>

если gcore недоступен в вашей системе, тогда

kill -ABRT <pid>

Не используйте kill -SEGV, так как это часто вызывает обработчик сигнала, что затрудняет диагностику зависшего процесса.

Я думаю, что гораздо более вероятно, что -ABRT вызовет обработчик сигнала, чем -SEGV, поскольку прерывание с большей вероятностью будет восстановлено, чем ошибка сегментации. (Если вы обрабатываете segfault, обычно он просто запускается снова, как только ваш обработчик завершает работу.) Лучшим выбором сигнала для генерации дампа ядра является -QUIT.

celticminstrel 26.02.2020 00:02

Чтобы проверить, где генерируются дампы ядра, запустите:

sysctl kernel.core_pattern

или же:

cat /proc/sys/kernel/core_pattern

где %e - это имя процесса, а %t - системное время. Вы можете поменять его в /etc/sysctl.conf и перезагрузить sysctl -p.

Если файлы ядра не генерируются (проверьте это: sleep 10 & и killall -SIGSEGV sleep), проверьте ограничения: ulimit -a.

Если размер вашего основного файла ограничен, запустите:

ulimit -c unlimited

сделать его безграничным.

Затем проверьте еще раз, если выгрузка ядра прошла успешно, вы увидите «(core dumped)» после индикации ошибки сегментации, как показано ниже:

Segmentation fault: 11 (core dumped)

См. Также: ядро сброшено - но файл ядра отсутствует в текущем каталоге?


Ubuntu

В Ubuntu дампы ядра обрабатываются Аппорт и могут находиться в /var/crash/. Однако в стабильных выпусках он по умолчанию отключен.

Для получения дополнительной информации, пожалуйста, проверьте: Где мне найти дамп ядра в Ubuntu?.

macOS

Для macOS см .: Как сгенерировать дампы ядра в Mac OS X?

Для Ubuntu, чтобы быстро вернуться к нормальному поведению (выгрузить файл ядра в текущий каталог), просто остановите службу аппорта с помощью «sudo service apport stop». Также обратите внимание, что если вы работаете в докере, этот параметр контролируется в хост-системе, а не в контейнере.

Digicrat 19.12.2017 03:37

Для Ubuntu 14.04

  1. Проверьте, включен ли дамп ядра:

    ulimit -a
    
  2. Одна из строк должна быть:

    core file size          (blocks, -c) unlimited
    
  3. Если не :

    gedit ~/.bashrc и добавьте ulimit -c unlimited в конец файла и сохраните, перезапустите терминал.

  4. Создайте свое приложение с отладочной информацией:

    В Makefile -O0 -g

  5. Запустите приложение, которое создает дамп ядра (файл дампа ядра с именем «core» должен быть создан рядом с файлом application_name):

    ./application_name
    
  6. Запускаем под gdb:

    gdb application_name core
    

На шаге 3, как «перезапустить» терминал? Вы имеете ввиду перезагрузку?

Naveen 30.06.2017 17:34

@Naveen нет, просто закройте терминал и откройте новый, также кажется, что вы можете просто поместить ulimit -c unlimited в терминал для временного решения, потому что только редактирование ~/.bashrc требует перезапуска терминала, чтобы изменения вступили в силу.

mrgloom 30.06.2017 18:59

Лучше программно включить дамп ядра с помощью системного вызова setrlimit.

пример:

#include <sys/resource.h>

bool enable_core_dump(){    
    struct rlimit corelim;

    corelim.rlim_cur = RLIM_INFINITY;
    corelim.rlim_max = RLIM_INFINITY;

    return (0 == setrlimit(RLIMIT_CORE, &corelim));
}

почему так лучше?

Nathan Fellman 26.08.2018 11:22

core-файл, созданный после сбоя, нет необходимости запускать ulimit -c unlimited в среде командной строки, а затем повторно запускать приложение.

kgbook 27.08.2018 09:47

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

Nathan Fellman 27.08.2018 21:23

В этом случае лучше использовать ulimit -c unlimited. Также вы можете скомпилировать с определением marco, приложение не будет включать символ enable_core_dump, если не определит этот макрос при выпуске, и вы получите замену дампа ядра отладочной версией.

kgbook 28.08.2018 10:38

даже если он определен макросом, это все равно требует от меня перекомпиляции, если я хочу сгенерировать дамп ядра, а не просто выполнить команду в оболочке перед повторным запуском.

Nathan Fellman 28.08.2018 11:57

Разработчику так удобно получить файл дампа ядра и более подробную отладочную информацию. В выпускной версии обычно компилируется с -O2 и без -g, и отладочная информация удалена или оптимизирована, и я контролирую все параметры отладки и дамп файла ядра, используя это определение marco в CMakeLists.txt или Makefile. У вас может быть свой выбор.

kgbook 28.08.2018 12:23

Стоит упомянуть, что если у вас настроен systemd, тогда все будет немного иначе. При настройке обычно основные файлы передаются по конвейеру с помощью значения sysctl core_pattern через systemd-coredump(8). Rlimit размера основного файла обычно уже настроен как "неограниченный".

Затем можно получить дампы ядра с помощью coredumpctl(1).

Хранилище дампов ядра и т.п. настраивается coredump.conf(5). На странице руководства coredumpctl есть примеры того, как получить файлы ядра, но вкратце это будет выглядеть так:

Найдите основной файл:

[vps@phoenix]~$ coredumpctl list test_me | tail -1
Sun 2019-01-20 11:17:33 CET   16163  1224  1224  11 present /home/vps/test_me

Получите файл ядра:

[vps@phoenix]~$ coredumpctl -o test_me.core dump 16163

Ubuntu 19.04

Сами по себе все остальные ответы мне не помогли. Но следующий итог сработал.

Создайте ~/.config/apport/settings со следующим содержимым:

[main]
unpackaged=true

(Это говорит apport также писать дампы ядра для пользовательских приложений)

чек: ulimit -c. Если он выводит 0, исправьте это с помощью

ulimit -c unlimited

На всякий случай перезапустите аппорт:

sudo systemctl restart apport

Файлы сбоев теперь записываются в /var/crash/. Но вы не можешь используете их с gdb. Чтобы использовать их с gdb, используйте

apport-unpack <location_of_report> <target_directory>

Дальнейшая информация:

  • В некоторых ответах предлагается изменить core_pattern. Имейте в виду, что этот файл может быть перезаписан службой аппорта при перезапуске.
  • Простая остановка аппорта не помогла
  • Значение ulimit -c может измениться автоматически, пока вы пробуете другие ответы в Интернете. Обязательно проверяйте его регулярно во время настройки создания дампа ядра.

Рекомендации:

Другие вопросы по теме