Bir segmentasyon hatası üzerinde Linux'ta bir çekirdek dökümü nasıl oluşturulur?


Yanıtlar:


249

Bu hangi kabuğu kullandığınıza bağlıdır. Bash kullanıyorsanız, ulimit komutu, program yürütmeyle ilgili olarak çekirdeği boşaltmanız gerekip gerekmediği gibi çeşitli ayarları denetler. Yazarsanız

ulimit -c unlimited

o zaman bash, programlarının herhangi bir boyuttaki çekirdeği dökebileceğini söyleyecektir. İsterseniz sınırsız yerine 52M gibi bir boyut belirtebilirsiniz, ancak uygulamada bu gerekli olmamalıdır çünkü çekirdek dosyaların boyutu muhtemelen sizin için bir sorun olmayacaktır.

Tcsh'de şunu yazarsınız:

limit coredumpsize unlimited

21
@lzprgmr: Açıklığa kavuşturmak için: çekirdek dökümlerinin varsayılan olarak oluşturulmamasının nedeni, sınırın ayarlanmaması ve / veya 0'a ayarlanmasıdır, bu da çekirdeğin dökülmesini önler. Sınırsız bir sınır belirleyerek, çekirdek dökümlerinin her zaman oluşturulabileceğini garanti ederiz.
Eli Courtwright

6
Bu bağlantı daha derine iner ve linux'da çekirdek dökümü oluşumunu sağlamak için daha fazla seçenek sunar. Tek dezavantajı bazı komutların / ayarların açıklanmamasıdır.
Salsa

6
4.1.2 (1) basında 52M gibi serbest bırakma sınırları belirtilemez, bu da geçersiz bir sayı hata mesajıyla sonuçlanır. Kılavuz sayfası, "Değerler 1024 baytlık artışlarla" olduğunu belirtir.
a1an

4
Bir zamanlar garip bir şey yapan ve X-server çökmesine neden olan "küçük" bir OpenGL projem vardı. Tekrar giriş yaptığımda, şirin bir 17 GB çekirdek dosya gördüm (25 GB'lik bir bölümde). Çekirdek dosyanın boyutunu sınırlı tutmak kesinlikle iyi bir fikir :)
IceCool

1
@PolarisUser: Bölümünüzün yenilmediğinden emin olmak istiyorsanız, 1 konser gibi bir sınır koymanızı öneririz. Kalan tüm sabit disk alanınızı tüketmekle tehdit etmezken, makul bir çekirdek dökümü için yeterli büyüklükte olmalıdır.
Eli Courtwright

60

Yukarıda açıklandığı gibi, burada sorulan gerçek soru, etkinleştirilmedikleri bir sistemde çekirdek dökümlerinin nasıl etkinleştirileceği. Bu soru burada cevaplanıyor.

Buraya, asılı bir işlem için çekirdek dökümü oluşturmayı öğrenmek için geldiyseniz, cevap

gcore <pid>

sisteminizde gcore yoksa o zaman

kill -ABRT <pid>

Kill -SEGV işlevini kullanmayın, çünkü bu genellikle sıkışmış işlemi teşhis etmeyi zorlaştıran bir sinyal işleyiciyi harekete geçirir


Ben bir kürtaj bir segfault daha kurtarılabilir olması daha muhtemel -ABRTolduğundan -SEGV, bir sinyal işleyicisi çağırmak çok daha muhtemel olduğunu düşünüyorum . (Bir segfault ile uğraşırsanız, normalde işleyiciniz çıkar çıkmaz tekrar tetiklenir.) Bir çekirdek dökümü oluşturmak için daha iyi bir sinyal seçimi -QUIT.
celticminstrel

32

Çekirdek dökümlerin nerede oluşturulduğunu kontrol etmek için şunu çalıştırın:

sysctl kernel.core_pattern

veya:

cat /proc/sys/kernel/core_pattern

%eişlem adı ve %tsistem saati nerede . İçinde değiştirebilirsiniz/etc/sysctl.conf ve yenidensysctl -p .

Çekirdek dosyalar oluşturulmazsa (tarafından test edin: sleep 10 &vekillall -SIGSEGV sleep ) ile sınırlarını kontrol: ulimit -a.

Temel dosya boyutunuz sınırlıysa, çalıştırın:

ulimit -c unlimited

sınırsız yapmak.

Sonra tekrar test edin, çekirdek boşaltma başarılı olursa, segmentasyon hatası göstergesinden sonra aşağıdaki gibi “(çekirdek boşaltma)” görürsünüz:

Segmentasyon hatası: 11 (çekirdek boşaltıldı)

Ayrıca bkz: çekirdek dökümü - ancak çekirdek dosya geçerli dizinde değil mi?


Ubuntu

Ubuntu'da çekirdek dökümler Apport tarafından işlenir ve içinde bulunabilir /var/crash/. Ancak, kararlı sürümlerde varsayılan olarak devre dışıdır.

Daha fazla ayrıntı için lütfen kontrol edin: Ubuntu'daki çekirdek dökümü nerede bulabilirim? .

Mac os işletim sistemi

MacOS için, bkz . Mac OS X'te çekirdek dökümleri nasıl oluşturulur?


3
Ubuntu için, hızlı bir şekilde normal davranışa geri dönmek (geçerli dizine bir çekirdek dosyayı dökmek) için, "sudo service apport stop" ile apport hizmetini durdurmanız yeterlidir. Ayrıca, bağlantı istasyonunda çalışıyorsanız, bu ayarın kapsayıcı içinde değil, ana bilgisayar sisteminde denetlendiğini unutmayın.
Digicrat

26

Sonunda yaptığım, çökmeden önce işleme gdb eklemek oldu ve sonra segfault aldığında generate-core-filekomutu yürüttüm . Çekirdek bir dökümün zorla üretilmesi.


Sürece gdb'yi nasıl eklediniz?
Chani

6
Ritwik G'ye cevap vermek için gdb'ye bir işlem eklemek için gdb'yi başlatın ve 'attach <pid>' girin; burada <pid>, eklemek istediğiniz işlemin pid numarasıdır.
Jean-Dominique Frattini

(kısaltılmış olarak ge)
user202729

Yeni bir soruları varsa, yorum sormak yerine yeni bir soru sormaları gerekir .
user202729

Garip şey zaten ayarlanmış ulimit -ciçin unlimited, ancak çekirdek dosyası hiçbir yaratılmış kabiliyetini kaybetmemiş olan, generate-core-filegdb oturumda dosya sayesinde çekirdek dosyası oluşturmak yapar.
CodyChan

19

Belki bu şekilde yapabilirsiniz, bu program bir segmentasyon hatası tuzak ve bir hata ayıklayıcı için kabukları (bu altında kullanılan orijinal kodudur AIX) ve yığın izlemesi bir segmentasyon hatası noktasına kadar yazdırır. Linux sprintfiçin kullanılacak değişkeni değiştirmeniz gerekecektir gdb.

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

Bu blogda burada gösterildiği gibi ek çekirdek dökümü olsun gdb bir parametre eklemek gerekebilir burada .


16

Bir çekirdek dökümü oluşumunu etkileyebilecek daha fazla şey var. Bunlarla karşılaştım:

  • döküm dizini yazılabilir olmalıdır. Varsayılan olarak bu işlemin geçerli dizinidir, ancak bu ayar ile değiştirilebilir/proc/sys/kernel/core_pattern .
  • bazı durumlarda, içindeki çekirdek değeri /proc/sys/fs/suid_dumpableçekirdeğin üretilmesini engelleyebilir.

Man sayfasında açıklanan nesli engelleyebilecek daha fazla durum vardır - deneyin man core.


9

Çekirdek dökümü etkinleştirmek için aşağıdakileri yapın:

  1. Yorumda /etc/profilesatır:

    # ulimit -S -c 0 > /dev/null 2>&1
  2. Gelen /etc/security/limits.confhat üzerinden comment:

    *               soft    core            0
  3. cmd'yi çalıştırın ve cmd limit coredumpsize unlimitedile kontrol edin 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 yazılıp yazılmadığını kontrol etmek için ilgili işlemi cmd ile öldürebilirsiniz kill -s SEGV <PID>(gerekli olmamalıdır, sadece çekirdek dosyanın yazılmaması durumunda bu bir kontrol olarak kullanılabilir):

    # kill -s SEGV <PID>

Core dosyası yazıldıktan sonra ilgili dosyalarda (1./2./3.) Coredump ayarlarını tekrar devre dışı bıraktığınızdan emin olun!


9

Ubuntu 14.04 için

  1. Çekirdek boşaltma etkin olup olmadığını kontrol edin:

    ulimit -a
  2. Çizgilerden biri şöyle olmalıdır:

    core file size          (blocks, -c) unlimited
  3. Değilse:

    gedit ~/.bashrcve ulimit -c unlimiteddosyanın sonuna ekleyin ve kaydedin, terminali yeniden çalıştırın.

  4. Hata ayıklama bilgileriyle uygulamanızı oluşturun:

    Makefile bölgesinde -O0 -g

  5. Çekirdek dökümü oluşturan uygulamayı çalıştırın ('core' adıyla çekirdek dökümü dosyası application_name dosyasının yakınında oluşturulmalıdır):

    ./application_name
  6. GDB altında çalıştırın:

    gdb application_name core

3. Adımda, terminal nasıl 'yeniden çalıştırılır'? Yeniden başlatma mı demek istediniz?
Naveen

@ Hayır, sadece terminali kapatın ve yeni bir tane açın, ulimit -c unlimitedgeçici çözüm için sadece terminali koyabileceğiniz gibi görünüyor , çünkü sadece düzenleme ~/.bashrc, değişikliklerin etkili olması için terminal kısıtlayıcısı gerektiriyor.
mrgloom

4

Varsayılan olarak bir çekirdek dosyası alırsınız. İşlemin geçerli dizininin yazılabilir olduğunu veya herhangi bir çekirdek dosya oluşturulmayacağını kontrol edin.


4
"Sürecin şu anki dizini" ile, işlemin yürütüldüğü sırada $ cwd demek istiyor musunuz? ~ / abc> / usr / bin / cat def, kedi çökerse, söz konusu geçerli dizin ~ / abc veya / usr / bin mi?
Nathan Fellman

5
~ / abc. Hmm, yorumların 15 karakter uzunluğunda olması gerekiyor!
Mark Harrison

5
Bu, SEGV sırasındaki geçerli dizin olacaktır. Ayrıca, gerçek kullanıcı / gruptan farklı etkili bir kullanıcı ve / veya grupla çalışan işlemler çekirdek dosyalar yazmaz.
Darron

2

Sistem aramasını kullanarak çekirdek dökümü programlı olarak açmak daha iyidir setrlimit.

misal:

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

neden daha iyi?
Nathan Fellman

çekirdek dosya çöktükten sonra oluşturulan, gerek yok ulimit -c unlimitedkomut satırı ortamında ve sonra uygulamayı yeniden çalıştırın.
kgbook

Her kullanıcı çöktüğünde bir çekirdek dökümü istemiyorum, sadece bir kullanıcı bana bakmak için geliştirici olarak başvurduğunda. 100 kez çökerse, bakmak için 100 çekirdeğe ihtiyacım yok.
Nathan Fellman

Bu durumda, kullanmak daha iyi ulimit -c unlimited. Ayrıca marco tanımı ile derleyebilirsiniz, uygulama enable_core_dumpserbest bırakıldığında bu makroyu tanımlamazsa sembol içermez ve hata ayıklama sürümü ile bir çekirdek dökümü alırsınız.
kgbook

bir makro tarafından nitelendirilmiş olsa bile, yeniden çalıştırmadan önce kabukta bir komut yürütmek yerine çekirdek dökümü oluşturmak istiyorsam yine de derlememi gerektirir.
Nathan Fellman

1

Eğer bir varsa söz It değerinde systemd setini, işler biraz farklı. Kurulum tipik olarak temel dosyaların core_patternsysctl değeri aracılığıyla iletilmesini sağlar systemd-coredump(8). Çekirdek dosya boyutu sınırı genellikle "sınırsız" olarak yapılandırılır.

Daha sonra kullanarak çekirdek döküntülerini almak mümkündür coredumpctl(1).

Çekirdek dökümlerin depolanması vb. İle yapılandırılır coredump.conf(5). Coredumpctl man sayfasındaki temel dosyaların nasıl alınacağına dair örnekler var, ancak kısaca şöyle görünecektir:

Çekirdek dosyayı bulun:

[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

Çekirdek dosyayı edinin:

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

0

Ubuntu 19.04

Diğer tüm cevaplar bana yardımcı olmadı. Ancak aşağıdaki özet, işi yaptı

Oluşturmak ~/.config/apport/settingsşu içeriğe sahip:

[main]
unpackaged=true

(Bu, apport'a ayrıca özel uygulamalar için temel dökümler yazmasını söyler)

kontrol edin ulimit -c. 0 çıktısı verirse,

ulimit -c unlimited

Sadece yeniden başlatma uygulamasında:

sudo systemctl restart apport

Kilitlenme dosyaları şimdi yazıldı /var/crash/. Ama olamaz gdb ile kullanabilirsiniz. Gdb ile kullanmak için

apport-unpack <location_of_report> <target_directory>

Daha fazla bilgi:

  • Bazı cevaplar değişmeyi önerir core_pattern . Bu dosyanın yeniden başlatma sırasında apport hizmeti tarafından üzerine yazılabileceğini unutmayın.
  • Basitçe apport durdurmak işi yapmadı
  • ulimit -cWeb'de diğer cevaplar çalışırlarken değer otomatik olarak değişmiş olabilir olsun. Çekirdek döküm oluşturma işleminizi ayarlarken düzenli olarak kontrol ettiğinizden emin olun.

Referanslar:

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.