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

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

20.08.2008 13:38:14
Как посмотреть его позже: stackoverflow.com/questions/8305866/…
Ciro Santilli 冠状病毒审查六四事件法轮功 14.04.2019 19:46:27
12 ОТВЕТОВ
РЕШЕНИЕ

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

ulimit -c unlimited

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

В tcsh вы наберете

limit coredumpsize unlimited
248
17.11.2008 22:22:13
@lzprgmr: чтобы уточнить: причина, по которой дампы ядра не создаются по умолчанию, заключается в том, что ограничение не установлено и / или не установлено в 0, что предотвращает сброс ядра. Устанавливая неограниченный лимит, мы гарантируем, что дампы ядра всегда будут генерироваться.
Eli Courtwright 9.08.2011 12:30:36
Эта ссылка идет глубже и дает еще несколько опций для включения генерации дампов ядра в linux. Единственным недостатком является то, что некоторые команды / настройки остаются необъясненными.
Salsa 31.08.2011 19:45:31
На bash 4.1.2 (1) -релиз ограничения не могут быть указаны, такие как 52M, что приводит к сообщению об ошибке неверного номера. Страница man говорит, что «Значения с шагом 1024 байта».
a1an 11.09.2012 12:02:57
Ну, у меня был «маленький» проект OpenGL, который когда-то делал странные вещи и вызывал сбой X-сервера. Когда я вернулся в систему, я увидел симпатичный маленький файл ядра объемом 17 ГБ (в разделе 25 ГБ). Это определенно хорошая идея, чтобы ограничить размер основного файла :)
IceCool 8.09.2013 15:48:55
@PolarisUser: Если вы хотите убедиться, что ваш раздел не съеден, я рекомендую установить ограничение примерно в 1 гиг. Это должно быть достаточно большим, чтобы справиться с любым разумным дампом ядра, при этом не угрожая использовать все оставшееся место на жестком диске.
Eli Courtwright 22.08.2014 16:51:58

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

4
20.08.2008 14:38:36
Под "текущим каталогом процесса" вы подразумеваете $ cwd во время запуска процесса? ~ / abc> / usr / bin / cat def в случае сбоя cat, является ли текущий каталог вопросом ~ / abc или / usr / bin?
Nathan Fellman 30.04.2009 07:52:00
~ / а. Хм, комментарии должны быть длиной 15 символов!
Mark Harrison 1.05.2009 14:56:59
Это будет текущий каталог во время SEGV. Кроме того, процессы, работающие с другим эффективным пользователем и / или группой, чем реальный пользователь / группа, не будут записывать файлы ядра.
Darron 26.01.2010 14:02:06

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

24
26.01.2010 13:33:27
Как вы подключили GDB к процессу?
Chani 31.05.2013 04:03:44
Чтобы ответить Ritwik G, чтобы прикрепить процесс к gdb, просто запустите gdb и введите attach <pid>, где <pid> - номер pid процесса, который вы хотите присоединить.
Jean-Dominique Frattini 13.06.2013 20:47:19
(сокращенно как ge)
user202729 24.06.2018 04:24:33
Если у них есть новый вопрос, они должны задать новый вопрос вместо того, чтобы спрашивать в комментарии.
user202729 24.06.2018 04:25:06

Может быть, вы могли бы сделать это таким образом, эта программа демонстрирует, как перехватить ошибку сегментации, и отправляет ее отладчику (это исходный код, используемый ниже 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 сбросить ядро , как показано здесь , в этом блоге здесь .

19
19.10.2016 06:50:41

Есть еще вещи, которые могут повлиять на генерацию дампа ядра. Я столкнулся с этим:

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

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

16
8.02.2012 10:31:21

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

  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. чтобы проверить, записан ли corefile, вы можете уничтожить связанный процесс с помощью cmd kill -s SEGV <PID>(не нужно, на всякий случай, если не записан основной файл, это можно использовать как проверку):

    # kill -s SEGV <PID>

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

9
5.04.2017 17:29:47

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

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

gcore <pid>

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

kill -ABRT <pid>

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

60
22.09.2016 20:51:05
Я думаю, что гораздо более вероятно, что -ABRTвызовет обработчик сигнала, чем -SEGV, поскольку прерывание с большей вероятностью будет восстановимо, чем сегфоут. (Если вы обрабатываете segfault, обычно он просто запускается снова, как только ваш обработчик завершается.) Лучший выбор сигнала для генерации дампа ядра - это -QUIT.
celticminstrel 25.02.2020 21:02:22

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

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

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

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

Ошибка сегментации: 11 (ядро сброшено)

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


Ubuntu

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

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

Macos

Для macOS см .: Как создать дамп ядра в Mac OS X?

29
15.01.2019 12:08:33
В Ubuntu, чтобы быстро вернуться к нормальному поведению (сбросить файл ядра в текущем каталоге), просто остановите службу apport с помощью «остановки приложения sudo service». Также обратите внимание, что если вы работаете в Docker, этот параметр контролируется в хост-системе, а не в контейнере.
Digicrat 19.12.2017 00:37:33

Для 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
9
25.01.2018 17:17:30
На шаге 3, как «перезапустить» терминал? Вы имеете в виду перезагрузку?
Naveen 30.06.2017 14:34:11
@ Навин нет, просто закройте терминал и откройте новый, также кажется, что вы можете просто вставить ulimit -c unlimitedтерминал для временного решения, потому что только редактирование ~/.bashrcтребует перезапуска терминала, чтобы изменения вступили в силу.
mrgloom 30.06.2017 15:59:29

Лучше включить программный дамп ядра с помощью системного вызова 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));
}
2
24.08.2018 08:52:59
почему так лучше?
Nathan Fellman 26.08.2018 08:22:25
Файл ядра генерируется после сбоя, не нужно ulimit -c unlimitedв командной строке среды, а затем перезапустить приложение.
kgbook 27.08.2018 06:47:24
Я не хочу дамп ядра каждый раз, когда он падает, только когда пользователь связывается со мной как разработчиком, чтобы посмотреть на него. Если он выходит из строя 100 раз, мне не нужно смотреть на 100 дампов ядра.
Nathan Fellman 27.08.2018 18:23:13
В этом случае лучше использовать ulimit -c unlimited. Также вы можете скомпилировать с определением marco, приложение не будет включать enable_core_dumpсимвол, если не определит этот макрос при выпуске, и вы получите дамп ядра, замененный отладочной версией.
kgbook 28.08.2018 07:38:55
даже если он определен макросом, мне все равно придется перекомпилировать, если я хочу сгенерировать дамп ядра, а не просто выполнить команду в оболочке перед повторным запуском.
Nathan Fellman 28.08.2018 08:57:16

Стоит отметить, что если у вас настроен systemd , то все немного по-другому. Обычно в настройках файлы ядра core_patternпередаются через значение sysctl через 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
1
20.01.2019 10:59:06

Ubuntu 19.04

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

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

[main]
unpackaged=true

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

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

ulimit -c unlimited

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

sudo systemctl restart apport

Crash файлы теперь записаны в /var/crash/. Но вы не можете использовать их с GDB. Чтобы использовать их с GDB, используйте

apport-unpack <location_of_report> <target_directory>

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

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

Ссылки:

0
28.10.2019 15:18:11