Wie generiere ich einen Core Dump unter Linux bei einem Segmentierungsfehler?


Antworten:


249

Dies hängt davon ab, welche Shell Sie verwenden. Wenn Sie bash verwenden, steuert der Befehl ulimit verschiedene Einstellungen in Bezug auf die Programmausführung, z. B. ob Sie den Core sichern sollten. Wenn Sie tippen

ulimit -c unlimited

dann wird das bash sagen, dass seine Programme Kerne jeder Größe ausgeben können. Sie können eine Größe wie 52 MB anstelle von unbegrenzt angeben, wenn Sie möchten. In der Praxis sollte dies jedoch nicht erforderlich sein, da die Größe der Kerndateien für Sie wahrscheinlich nie ein Problem darstellt.

In tcsh würden Sie eingeben

limit coredumpsize unlimited

21
@lzprgmr: Zur Verdeutlichung: Der Grund, warum Core-Dumps nicht standardmäßig generiert werden, ist, dass das Limit nicht festgelegt und / oder auf 0 gesetzt ist, wodurch verhindert wird, dass der Core-Dump ausgeführt wird. Durch die Festlegung eines unbegrenzten Limits garantieren wir, dass immer Core-Dumps generiert werden können.
Eli Courtwright

6
Dieser Link geht tiefer und bietet einige weitere Optionen, um die Generierung von Core-Dumps unter Linux zu ermöglichen. Der einzige Nachteil ist, dass einige Befehle / Einstellungen ungeklärt bleiben.
Salsa

6
In Bash 4.1.2 (1) können keine Freigabegrenzen wie 52M angegeben werden, was zu einer ungültigen Nummernfehlermeldung führt. Die Manpage gibt an, dass "Werte in Schritten von 1024 Byte angegeben sind".
a1an

4
Nun, ich hatte ein "kleines" OpenGL-Projekt, das einmal etwas Seltsames getan hat und einen Absturz des X-Servers verursacht hat. Als ich mich zurückmeldete, sah ich eine niedliche kleine 17-GB-Kerndatei (auf einer 25-GB-Partition). Es ist definitiv eine gute Idee, die Größe der Kerndatei begrenzt zu halten :)
IceCool

1
@PolarisUser: Wenn Sie sicherstellen möchten, dass Ihre Partition nicht gegessen wird, empfehle ich, ein Limit von etwa 1 Gig festzulegen. Das sollte groß genug sein, um jeden vernünftigen Core-Dump zu verarbeiten, ohne den gesamten verbleibenden Festplattenspeicher zu verbrauchen.
Eli Courtwright

60

Wie oben erläutert, wird hier die eigentliche Frage gestellt, wie Core Dumps auf einem System aktiviert werden können, auf dem sie nicht aktiviert sind. Diese Frage wird hier beantwortet.

Wenn Sie hierher gekommen sind, um zu erfahren, wie Sie einen Core-Dump für einen blockierten Prozess generieren, lautet die Antwort

gcore <pid>

Wenn gcore auf Ihrem System nicht verfügbar ist, dann

kill -ABRT <pid>

Verwenden Sie kill -SEGV nicht, da dies häufig einen Signalhandler aufruft, der die Diagnose des festgefahrenen Prozesses erschwert


Ich denke, es ist weitaus wahrscheinlicher, dass -ABRTein Signal-Handler -SEGVaufgerufen wird als , da ein Abbruch eher wiederherstellbar ist als ein Segfault. (Wenn Sie einen Segfault behandeln, wird dieser normalerweise erst wieder ausgelöst, sobald Ihr Handler beendet wird.) Eine bessere Signalauswahl für die Erzeugung eines Core-Dumps ist -QUIT.
Celticminstrel

32

Führen Sie Folgendes aus, um zu überprüfen, wo die Core-Dumps generiert werden:

sysctl kernel.core_pattern

oder:

cat /proc/sys/kernel/core_pattern

Wo %eist der Prozessname und %tdie Systemzeit. Sie können es ändern /etc/sysctl.confund neu laden durch sysctl -p.

Wenn die Kerndateien nicht generiert werden (testen Sie sie mit: sleep 10 &und killall -SIGSEGV sleep), überprüfen Sie die Grenzwerte mit : ulimit -a.

Wenn Ihre Kerndateigröße begrenzt ist, führen Sie Folgendes aus:

ulimit -c unlimited

um es unbegrenzt zu machen.

Testen Sie dann erneut, ob das Core-Dumping erfolgreich ist. Nach der Anzeige des Segmentierungsfehlers wird "(Core-Dumping)" angezeigt:

Segmentierungsfehler: 11 (Core Dumped)

Siehe auch: Core Dumped - aber Core-Datei befindet sich nicht im aktuellen Verzeichnis?


Ubuntu

In Ubuntu werden die Core-Dumps von Apport verwaltet und können sich in befinden /var/crash/. In stabilen Releases ist es jedoch standardmäßig deaktiviert.

Weitere Informationen finden Sie unter: Wo finde ich den Core Dump in Ubuntu? .

Mac OS

Informationen zu macOS finden Sie unter: Wie werden Core-Dumps in Mac OS X generiert?


3
Damit Ubuntu schnell zum normalen Verhalten zurückkehren kann (Speichern einer Kerndatei im aktuellen Verzeichnis), beenden Sie einfach den Apport-Dienst mit "sudo service apport stop". Beachten Sie außerdem, dass diese Einstellung auf dem Hostsystem und nicht im Container gesteuert wird, wenn Sie im Docker ausgeführt werden.
Digicrat

26

Was ich am Ende getan habe, war, gdb an den Prozess anzuhängen, bevor er abstürzte, und dann, als er den Segfault bekam, habe ich den generate-core-fileBefehl ausgeführt. Diese erzwungene Erzeugung eines Kerndumps.


Wie haben Sie gdb an den Prozess angehängt?
Chani

6
Um auf Ritwik G zu antworten und einen Prozess an gdb anzuhängen, starten Sie einfach gdb und geben Sie 'attach <pid>' ein, wobei <pid> die Pid-Nummer des Prozesses ist, den Sie anhängen möchten.
Jean-Dominique Frattini

(abgekürzt als ge)
user202729

Wenn sie eine neue Frage haben, sollten sie eine neue Frage stellen, anstatt sie in einem Kommentar zu stellen.
user202729

Seltsame Sache ist, dass ich bereits eingestellt ulimit -chabe unlimited, aber die Kerndatei ist noch nicht erstellt, die generate-core-fileDatei in der GDB-Sitzung erstellt die Kerndatei, danke.
CodyChan

19

Vielleicht könnten Sie es auf diese Weise tun. Dieses Programm ist eine Demonstration, wie ein Segmentierungsfehler abgefangen und an einen Debugger weitergeleitet wird (dies ist der ursprüngliche Code, der unter verwendet wird AIX), und druckt die Stapelverfolgung bis zum Punkt eines Segmentierungsfehlers. Sie müssen die sprintfVariable ändern, die gdbim Fall von Linux verwendet werden soll.

#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 */
}

Möglicherweise müssen Sie zusätzlich einen Parameter hinzufügen, damit gdb den Kern entleert, wie hier in diesem Blog hier gezeigt .


16

Es gibt weitere Faktoren, die die Erzeugung eines Core-Dumps beeinflussen können. Ich bin auf Folgendes gestoßen:

  • Das Verzeichnis für den Speicherauszug muss beschreibbar sein. Standardmäßig ist dies das aktuelle Verzeichnis des Prozesses. Dies kann jedoch durch Festlegen geändert werden /proc/sys/kernel/core_pattern.
  • Unter bestimmten Umständen kann der Kernelwert in /proc/sys/fs/suid_dumpableverhindern, dass der Kern generiert wird.

Es gibt weitere Situationen, die die in der Manpage beschriebene Generierung verhindern können man core.


9

Gehen Sie wie folgt vor, um den Core Dump zu aktivieren:

  1. Im /etc/profileKommentar der Zeile:

    # ulimit -S -c 0 > /dev/null 2>&1
  2. Im /etc/security/limits.confKommentar aus der Zeile:

    *               soft    core            0
  3. Führen Sie das cmd aus limit coredumpsize unlimitedund überprüfen Sie es mit 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. Um zu überprüfen, ob die Core-Datei geschrieben wird, können Sie den zugehörigen Prozess mit cmd beenden kill -s SEGV <PID>(sollte nicht benötigt werden, nur für den Fall, dass keine Core-Datei geschrieben wird, kann dies als Überprüfung verwendet werden):

    # kill -s SEGV <PID>

Nachdem die Corefile geschrieben wurde, müssen Sie die Coredump-Einstellungen in den zugehörigen Dateien (1./2./3.) Wieder deaktivieren!


9

Für Ubuntu 14.04

  1. Überprüfen Sie, ob der Core Dump aktiviert ist:

    ulimit -a
  2. Eine der Zeilen sollte sein:

    core file size          (blocks, -c) unlimited
  3. Wenn nicht :

    gedit ~/.bashrcund ulimit -c unlimitedam Ende der Datei hinzufügen und speichern, Terminal erneut ausführen.

  4. Erstellen Sie Ihre Anwendung mit Debug-Informationen:

    In Makefile -O0 -g

  5. Führen Sie eine Anwendung aus, die einen Core-Dump erstellt (Core-Dump-Datei mit dem Namen 'core' sollte in der Nähe der Datei application_name erstellt werden):

    ./application_name
  6. Unter gdb ausführen:

    gdb application_name core

In Schritt 3, Wie wird das Terminal erneut ausgeführt? Meinst du Neustart?
Naveen

@Naveen Nein, schließen Sie einfach das Terminal und öffnen Sie das neue. Anscheinend können Sie das ulimit -c unlimitedTerminal auch nur für eine temporäre Lösung ~/.bashrceinfügen , da nur für die Bearbeitung ein Neustart des Terminals erforderlich ist, damit Änderungen wirksam werden.
Mrgloom

4

Standardmäßig erhalten Sie eine Kerndatei. Überprüfen Sie, ob das aktuelle Verzeichnis des Prozesses beschreibbar ist oder keine Kerndatei erstellt wird.


4
Mit "aktuelles Verzeichnis des Prozesses" meinen Sie das $ cwd zum Zeitpunkt der Ausführung des Prozesses? ~ / abc> / usr / bin / cat def Wenn cat abstürzt, ist das aktuelle Verzeichnis in Frage ~ / abc oder / usr / bin?
Nathan Fellman

5
~ / abc. Hmm, Kommentare müssen 15 Zeichen lang sein!
Mark Harrison

5
Dies wäre das aktuelle Verzeichnis zum Zeitpunkt der SEGV. Außerdem schreiben Prozesse, die mit einem anderen effektiven Benutzer und / oder einer anderen Gruppe als dem tatsächlichen Benutzer / der tatsächlichen Gruppe ausgeführt werden, keine Kerndateien.
Darron

2

Es ist besser, den Core Dump mithilfe eines Systemaufrufs programmgesteuert einzuschalten setrlimit.

Beispiel:

#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));
}

warum ist das besser
Nathan Fellman

Kerndatei nach dem Absturz generiert, keine Notwendigkeit ulimit -c unlimitedin der Befehlszeilenumgebung, und dann die Anwendung erneut ausführen.
kgbook

Ich möchte nicht jedes Mal einen Core-Dump, wenn er abstürzt, nur wenn ein Benutzer mich als Entwickler kontaktiert, um ihn anzusehen. Wenn es 100 Mal abstürzt, brauche ich keine 100 Core-Dumps zum Anschauen.
Nathan Fellman

In diesem Fall besser zu verwenden ulimit -c unlimited. Sie können auch mit marco definition kompilieren. Die Anwendung enthält kein enable_core_dumpSymbol, wenn dieses Makro bei der Veröffentlichung nicht definiert wird, und Sie erhalten einen Core-Dump, der durch die Debug-Version ersetzt wird.
kgbook

Selbst wenn es durch ein Makro qualifiziert ist, muss ich dennoch neu kompilieren, wenn ich einen Core-Dump generieren möchte, anstatt einfach einen Befehl in der Shell auszuführen, bevor ich ihn erneut ausführe.
Nathan Fellman

1

Es ist erwähnenswert, dass, wenn Sie ein System eingerichtet haben, die Dinge ein bisschen anders sind. Bei der Einrichtung werden die Kerndateien normalerweise mithilfe des core_patternsysctl-Werts durchgeleitet systemd-coredump(8). Die Kerndateigröße rlimit wird normalerweise bereits als "unbegrenzt" konfiguriert.

Es ist dann möglich, die Core-Dumps mit abzurufen coredumpctl(1).

Die Speicherung von Core Dumps usw. wird von konfiguriert coredump.conf(5). Es gibt Beispiele, wie Sie die Kerndateien in der Manpage coredumpctl abrufen können, aber kurz gesagt würde es so aussehen:

Suchen Sie die Kerndatei:

[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

Holen Sie sich die Kerndatei:

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

0

Ubuntu 19.04

Alle anderen Antworten selbst haben mir nicht geholfen. Aber die folgende Zusammenfassung hat den Job gemacht

Erstellen Sie ~/.config/apport/settingsmit folgendem Inhalt:

[main]
unpackaged=true

(Dies weist Apport an, auch Core-Dumps für benutzerdefinierte Apps zu schreiben.)

überprüfen : ulimit -c. Wenn es 0 ausgibt, beheben Sie es mit

ulimit -c unlimited

Nur für den Fall, dass Apport neu gestartet wird:

sudo systemctl restart apport

Absturzdateien werden jetzt geschrieben /var/crash/. Sie können sie jedoch nicht mit gdb verwenden. Um sie mit gdb zu verwenden, verwenden Sie

apport-unpack <location_of_report> <target_directory>

Weitere Informationen:

  • Einige Antworten schlagen eine Änderung vor core_pattern. Beachten Sie, dass diese Datei beim Neustart möglicherweise vom Apport-Dienst überschrieben wird.
  • Das einfache Stoppen von Apport hat den Job nicht erledigt
  • Der ulimit -cWert wird möglicherweise automatisch geändert, wenn Sie andere Antworten im Web ausprobieren. Überprüfen Sie dies regelmäßig, während Sie die Erstellung Ihres Core-Dumps einrichten.

Verweise:

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.