Wie generiere ich einen Core Dump unter Linux bei einem Segmentierungsfehler?
217
Ich habe einen Prozess unter Linux, bei dem ein Segmentierungsfehler auftritt. Wie kann ich ihm sagen, dass er einen Core-Dump generieren soll, wenn er fehlschlägt?
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.
@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:
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.
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.
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);return0;}
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
**Section6.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 .
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.
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!
gedit ~/.bashrcund ulimit -c unlimitedam Ende der Datei hinzufügen und speichern, Terminal erneut ausführen.
Erstellen Sie Ihre Anwendung mit Debug-Informationen:
In Makefile -O0 -g
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):
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.
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.
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 -1Sun2019-01-2011:17:33 CET 161631224122411 present /home/vps/test_me
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.
Antworten:
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
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
quelle
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
Wenn gcore auf Ihrem System nicht verfügbar ist, dann
Verwenden Sie kill -SEGV nicht, da dies häufig einen Signalhandler aufruft, der die Diagnose des festgefahrenen Prozesses erschwert
quelle
-ABRT
ein Signal-Handler-SEGV
aufgerufen 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
.Führen Sie Folgendes aus, um zu überprüfen, wo die Core-Dumps generiert werden:
oder:
Wo
%e
ist der Prozessname und%t
die Systemzeit. Sie können es ändern/etc/sysctl.conf
und neu laden durchsysctl -p
.Wenn die Kerndateien nicht generiert werden (testen Sie sie mit:
sleep 10 &
undkillall -SIGSEGV sleep
), überprüfen Sie die Grenzwerte mit :ulimit -a
.Wenn Ihre Kerndateigröße begrenzt ist, führen Sie Folgendes aus:
um es unbegrenzt zu machen.
Testen Sie dann erneut, ob das Core-Dumping erfolgreich ist. Nach der Anzeige des Segmentierungsfehlers wird "(Core-Dumping)" angezeigt:
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?
quelle
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-file
Befehl ausgeführt. Diese erzwungene Erzeugung eines Kerndumps.quelle
ge
)ulimit -c
habeunlimited
, aber die Kerndatei ist noch nicht erstellt, diegenerate-core-file
Datei in der GDB-Sitzung erstellt die Kerndatei, danke.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 diesprintf
Variable ändern, diegdb
im Fall von Linux verwendet werden soll.Möglicherweise müssen Sie zusätzlich einen Parameter hinzufügen, damit gdb den Kern entleert, wie hier in diesem Blog hier gezeigt .
quelle
Es gibt weitere Faktoren, die die Erzeugung eines Core-Dumps beeinflussen können. Ich bin auf Folgendes gestoßen:
/proc/sys/kernel/core_pattern
./proc/sys/fs/suid_dumpable
verhindern, dass der Kern generiert wird.Es gibt weitere Situationen, die die in der Manpage beschriebene Generierung verhindern können
man core
.quelle
Gehen Sie wie folgt vor, um den Core Dump zu aktivieren:
Im
/etc/profile
Kommentar der Zeile:Im
/etc/security/limits.conf
Kommentar aus der Zeile:Führen Sie das cmd aus
limit coredumpsize unlimited
und überprüfen Sie es mit cmdlimit
: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):Nachdem die Corefile geschrieben wurde, müssen Sie die Coredump-Einstellungen in den zugehörigen Dateien (1./2./3.) Wieder deaktivieren!
quelle
Für Ubuntu 14.04
Überprüfen Sie, ob der Core Dump aktiviert ist:
Eine der Zeilen sollte sein:
Wenn nicht :
gedit ~/.bashrc
undulimit -c unlimited
am Ende der Datei hinzufügen und speichern, Terminal erneut ausführen.Erstellen Sie Ihre Anwendung mit Debug-Informationen:
In Makefile
-O0 -g
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):
Unter gdb ausführen:
quelle
ulimit -c unlimited
Terminal auch nur für eine temporäre Lösung~/.bashrc
einfügen , da nur für die Bearbeitung ein Neustart des Terminals erforderlich ist, damit Änderungen wirksam werden.Standardmäßig erhalten Sie eine Kerndatei. Überprüfen Sie, ob das aktuelle Verzeichnis des Prozesses beschreibbar ist oder keine Kerndatei erstellt wird.
quelle
Es ist besser, den Core Dump mithilfe eines Systemaufrufs programmgesteuert einzuschalten
setrlimit
.Beispiel:
quelle
ulimit -c unlimited
in der Befehlszeilenumgebung, und dann die Anwendung erneut ausführen.ulimit -c unlimited
. Sie können auch mit marco definition kompilieren. Die Anwendung enthält keinenable_core_dump
Symbol, wenn dieses Makro bei der Veröffentlichung nicht definiert wird, und Sie erhalten einen Core-Dump, der durch die Debug-Version ersetzt wird.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_pattern
sysctl-Werts durchgeleitetsystemd-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:
Holen Sie sich die Kerndatei:
quelle
Ubuntu 19.04
Alle anderen Antworten selbst haben mir nicht geholfen. Aber die folgende Zusammenfassung hat den Job gemacht
Erstellen Sie
~/.config/apport/settings
mit folgendem Inhalt:(Dies weist Apport an, auch Core-Dumps für benutzerdefinierte Apps zu schreiben.)
überprüfen :
ulimit -c
. Wenn es 0 ausgibt, beheben Sie es mitNur für den Fall, dass Apport neu gestartet wird:
Absturzdateien werden jetzt geschrieben
/var/crash/
. Sie können sie jedoch nicht mit gdb verwenden. Um sie mit gdb zu verwenden, verwenden SieWeitere Informationen:
core_pattern
. Beachten Sie, dass diese Datei beim Neustart möglicherweise vom Apport-Dienst überschrieben wird.ulimit -c
Wert 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:
quelle