Сведения о вопросе

HOLY

16:53, 5th August, 2020

Теги

linux   bash   unix   coredump   tcsh    

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

Просмотров: 483   Ответов: 12

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



  Сведения об ответе

PIRLO

20:18, 11th August, 2020

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

ulimit -c unlimited

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

В tcsh вы бы набрали

limit coredumpsize unlimited


  Сведения об ответе

PAGE

05:59, 17th August, 2020

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

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

gcore <pid>

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

kill -ABRT <pid>

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


  Сведения об ответе

appple

09:45, 13th August, 2020

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


  Сведения об ответе

lourence

21:06, 1st October, 2020

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

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?


  Сведения об ответе

+-*/

12:03, 4th August, 2020

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


  Сведения об ответе

park

13:30, 5th August, 2020

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

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

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


  Сведения об ответе

JUST___

03:39, 26th August, 2020

Для активации дампа ядра выполните следующие действия:

  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.) !


  Сведения об ответе

prince

08:02, 13th August, 2020

Для Ubuntu 14.04

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

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

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

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

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

    В Файле Makefile -O0 -g

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

    ./application_name
    
  6. Работать под gdb:

    gdb application_name core
    


  Сведения об ответе

lesha

20:01, 25th August, 2020

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


  Сведения об ответе

padenie

15:17, 4th August, 2020

Лучше включить дамп ядра программно, используя системный вызов 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));
}


  Сведения об ответе

PIRLO

11:56, 17th August, 2020

Подождите. Это происходит автоматически. Нет необходимости делать это


  Сведения об ответе

PROGA

23:16, 23rd August, 2020

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

Затем можно получить основные дампы, используя coredumpctl(1) .

Хранение дампов и т. д. настроен на coredump.conf(5) . Есть примеры того, как получить основные файлы на man-странице 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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться