วิธีการสร้างการถ่ายโอนข้อมูลหลักใน Linux บนข้อผิดพลาดการแบ่งส่วน?


217

ฉันมีกระบวนการใน Linux ที่ได้รับการแบ่งกลุ่มผิดพลาด ฉันจะบอกให้สร้างคอร์ดัมพ์เมื่อมันล้มเหลวได้อย่างไร


คำตอบ:


249

ขึ้นอยู่กับว่าคุณใช้เชลล์อะไร หากคุณกำลังใช้ bash คำสั่ง ulimit จะควบคุมการตั้งค่าต่าง ๆ ที่เกี่ยวข้องกับการทำงานของโปรแกรมเช่นว่าคุณควรถ่ายโอนข้อมูลหลักหรือไม่ ถ้าคุณพิมพ์

ulimit -c unlimited

จากนั้นจะบอกว่าทุบตีโปรแกรมของมันสามารถทิ้งแกนขนาดใดก็ได้ คุณสามารถระบุขนาดเช่น 52M แทนไม่ จำกัด หากคุณต้องการ แต่ในทางปฏิบัติสิ่งนี้ไม่จำเป็นเพราะขนาดของไฟล์หลักอาจไม่เป็นปัญหาสำหรับคุณ

ใน tcsh คุณจะต้องพิมพ์

limit coredumpsize unlimited

21
@lzprgmr: เพื่อชี้แจง: เหตุผลที่การทิ้งขยะหลักไม่ได้สร้างขึ้นตามค่าเริ่มต้นคือไม่ได้ตั้งค่าขีด จำกัด และ / หรือตั้งค่าเป็น 0 ซึ่งป้องกันไม่ให้แกนทิ้ง โดยการตั้งค่าขีด จำกัด ไม่ จำกัด เรารับประกันว่าสามารถทิ้งขยะหลักได้ตลอดเวลา
Eli Courtwright

6
ลิงค์นี้ลึกลงไปและให้ตัวเลือกเพิ่มเติมเพื่อเปิดใช้งานการสร้างทิ้งหลักในลินุกซ์ ข้อเสียเปรียบเพียงอย่างเดียวคือคำสั่ง / การตั้งค่าบางอย่างถูกทิ้งไว้โดยไม่ได้อธิบาย
ซัลซ่า

6
ใน bash 4.1.2 (1) - ไม่อนุญาตให้ จำกัด เช่น 52M ซึ่งจะส่งผลให้เกิดข้อผิดพลาดเกี่ยวกับตัวเลขที่ไม่ถูกต้อง หน้าคนบอกว่า "ค่ามีการเพิ่มขึ้นทีละ 1024 ไบต์"
a1an

4
ฉันมีโครงการ OpenGL "เล็ก ๆ " ซึ่งครั้งหนึ่งเคยทำสิ่งประหลาดและทำให้เซิร์ฟเวอร์ X-crash เมื่อฉันกลับเข้าสู่ระบบฉันเห็นไฟล์หลักขนาด 17 GB น่ารัก (ในพาร์ติชัน 25 GB) เป็นความคิดที่ดีที่จะรักษาขนาดของไฟล์คอร์ไว้อย่างแน่นอน :)
IceCool

1
@PolarisUser: ถ้าคุณต้องการให้แน่ใจว่าพาร์ทิชันของคุณไม่ได้กินฉันขอแนะนำให้ตั้งค่าขีด จำกัด ของบางอย่างเช่น 1 กิ๊ก นั่นควรจะมีขนาดใหญ่พอที่จะรองรับการถ่ายโอนข้อมูลหลักที่สมเหตุสมผลในขณะที่ไม่ได้ใช้พื้นที่ฮาร์ดไดรฟ์ที่เหลืออยู่ทั้งหมด
Eli Courtwright

60

ดังที่อธิบายไว้ข้างต้นคำถามจริงที่ถูกถามที่นี่คือวิธีการเปิดใช้งานการถ่ายโอนข้อมูลหลักบนระบบที่ไม่ได้เปิดใช้งาน คำถามนั้นตอบที่นี่

หากคุณมาที่นี่โดยหวังที่จะเรียนรู้วิธีสร้างการถ่ายโอนข้อมูลหลักสำหรับกระบวนการที่หยุดทำงานคำตอบคือ

gcore <pid>

ถ้า gcore ไม่สามารถใช้ได้ในระบบของคุณแล้ว

kill -ABRT <pid>

อย่าใช้ kill -SEGV เนื่องจากมักจะเรียกตัวจัดการสัญญาณทำให้การวินิจฉัยกระบวนการที่ติดอยู่ยากขึ้น


ฉันคิดว่าเป็นไปได้มากกว่าที่-ABRTจะเรียกใช้ตัวจัดการสัญญาณมากกว่า-SEGVเนื่องจากการยกเลิกมีแนวโน้มที่จะกู้คืนได้มากกว่า segfault (ถ้าคุณจัดการ segfault ที่ปกติมันก็จะเรียกอีกครั้งทันทีที่ออกจากการจัดการของคุณ.) -QUITทางเลือกที่ดีกว่าของสัญญาณสำหรับการสร้างถ่ายโอนข้อมูลหลักคือ
celticminstrel

32

ในการตรวจสอบตำแหน่งที่ทิ้งขยะหลักให้สร้าง:

sysctl kernel.core_pattern

หรือ:

cat /proc/sys/kernel/core_pattern

โดยที่%eชื่อกระบวนการและ%tเวลาของระบบ คุณสามารถเปลี่ยนได้ในและโหลดโดย/etc/sysctl.confsysctl -p

หากไฟล์หลักไม่ได้ถูกสร้าง (ทดสอบได้โดย: sleep 10 &และkillall -SIGSEGV sleep) ให้ตรวจสอบข้อ จำกัด ulimit -aโดย:

หากขนาดไฟล์หลักของคุณถูก จำกัด ให้รัน:

ulimit -c unlimited

เพื่อให้ไม่ จำกัด

จากนั้นทดสอบอีกครั้งหากการถ่ายโอนข้อมูลหลักประสบความสำเร็จคุณจะเห็น“ (การถ่ายโอนข้อมูลหลัก)” หลังจากการบ่งชี้ข้อผิดพลาดการแบ่งกลุ่มดังต่อไปนี้:

การแบ่งส่วนความผิดพลาด: 11 (ทิ้งหลัก)

ดูเพิ่มเติม: แกนทิ้ง - แต่ไฟล์หลักไม่ได้อยู่ในไดเรกทอรีปัจจุบัน?


อูบุนตู

ใน Ubuntu ทิ้งหลักจะถูกจัดการโดยApport/var/crash/และสามารถอยู่ใน อย่างไรก็ตามจะถูกปิดใช้งานตามค่าเริ่มต้นในรุ่นที่เสถียร

สำหรับรายละเอียดเพิ่มเติมโปรดตรวจสอบ: ฉันจะหา core dump ใน Ubuntu ได้ที่ไหน? .

MacOS

สำหรับ macOS โปรดดู: วิธีสร้างการถ่ายโอนข้อมูลหลักใน Mac OS X ได้อย่างไร


3
สำหรับ Ubuntu เพื่อย้อนกลับสู่พฤติกรรมปกติได้อย่างรวดเร็ว (ทิ้งไฟล์หลักในไดเรกทอรีปัจจุบัน) เพียงแค่หยุดบริการ apport ด้วย "หยุดบริการ sudo apport stop" นอกจากนี้โปรดทราบว่าหากคุณกำลังทำงานภายในตัวเชื่อมต่อการตั้งค่านั้นจะถูกควบคุมในระบบโฮสต์และไม่ได้อยู่ในคอนเทนเนอร์
Digicrat

26

สิ่งที่ฉันทำในตอนท้ายคือการแนบ gdb กับกระบวนการก่อนที่มันจะผิดพลาดและเมื่อมันได้รับ segfault ฉันดำเนินการgenerate-core-fileคำสั่ง การบังคับให้สร้างแกนดัมพ์


คุณแนบ gdb เข้ากับกระบวนการได้อย่างไร
Chani

6
หากต้องการตอบ Ritwik G หากต้องการแนบกระบวนการกับ gdb เพียงเปิดใช้ gdb และป้อน 'แนบ <pid>' โดยที่ <pid> คือหมายเลข pid ของกระบวนการที่คุณต้องการแนบ
Jean-Dominique Frattini

(ตัวย่อเป็นge)
user202729

หากพวกเขามีคำถามใหม่พวกเขาควรถามคำถามใหม่แทนที่จะถามในความคิดเห็น
user202729

สิ่งที่แปลกคือผมตั้งแล้วulimit -cไปunlimitedแต่ไฟล์หลักคือการสร้างนิ่งไม่มีgenerate-core-fileแฟ้มในเซสชั่น gdb ไม่สร้างไฟล์หลักขอบคุณ
CodyChan

19

บางทีคุณสามารถทำได้ด้วยวิธีนี้โปรแกรมนี้เป็นการสาธิตวิธีดักจับการแบ่งเซกเมนต์และเชลล์ออกไปยังดีบั๊ก (นี่คือรหัสต้นฉบับที่ใช้ภายใต้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 หลักที่แสดงที่นี่ในบล็อกนี้ที่นี่


16

มีหลายสิ่งที่อาจมีผลต่อการสร้างดัมพ์หลัก ฉันพบสิ่งเหล่านี้:

  • ไดเรกทอรีสำหรับการถ่ายโอนข้อมูลจะต้องเขียนได้ โดยค่าเริ่มต้นนี้เป็นไดเรกทอรีปัจจุบันของกระบวนการ /proc/sys/kernel/core_patternแต่ที่อาจมีการเปลี่ยนแปลงโดยการตั้งค่า
  • ในบางเงื่อนไขค่าเคอร์เนลใน/proc/sys/fs/suid_dumpableอาจป้องกันแกนที่จะสร้าง

มีสถานการณ์มากขึ้นซึ่งอาจป้องกันไม่ให้รุ่นที่อธิบายไว้ในหน้าคนมี - man coreลอง


9

เพื่อเปิดใช้งานการถ่ายโอนข้อมูลหลักทำต่อไปนี้:

  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>(ไม่จำเป็นต้องใช้ในกรณีที่ไม่มีไฟล์ core ที่เขียนสิ่งนี้สามารถใช้เป็นการตรวจสอบ):

    # kill -s SEGV <PID>

เมื่อเขียน corefile แล้วให้ปิดการตั้งค่า coredump อีกครั้งในไฟล์ที่เกี่ยวข้อง (1./2./3)


9

สำหรับ 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 dump (ไฟล์ dump หลักที่มีชื่อ 'core' ควรสร้างใกล้กับไฟล์ application_name):

    ./application_name
  6. ทำงานภายใต้ gdb:

    gdb application_name core

ในขั้นตอนที่ 3 วิธีการ 'เรียกใช้ซ้ำ' เทอร์มินัล คุณหมายถึงการรีบูตหรือไม่
Naveen

@ ไม่มีไม่เพียงปิดเทอร์มินัลแล้วเปิดใหม่ก็ดูเหมือนว่าคุณสามารถใส่ulimit -c unlimitedเทอร์มินัลสำหรับการแก้ปัญหาชั่วคราวเพราะการแก้ไขเฉพาะ~/.bashrcต้องการเทอร์มินัลสำหรับการเปลี่ยนแปลงที่จะทำให้เกิดผล
mrgloom

4

โดยค่าเริ่มต้นคุณจะได้รับไฟล์หลัก ตรวจสอบเพื่อดูว่าไดเรกทอรีปัจจุบันของกระบวนการสามารถเขียนได้หรือไม่มีไฟล์หลักที่จะถูกสร้างขึ้น


4
โดย "ไดเรกทอรีปัจจุบันของกระบวนการ" คุณหมายถึง $ cwd ณ เวลาที่กระบวนการทำงานหรือไม่ ~ / abc> / usr / bin / cat def หาก cat crashes เป็นไดเรกทอรีปัจจุบันในคำถาม ~ / abc หรือ / usr / bin หรือไม่
30919 Nathan Fellman เมื่อ

5
~ / abc อืมความคิดเห็นต้องมีความยาว 15 ตัวอักษร!
Mark Harrison

5
นี่จะเป็นไดเรกทอรีปัจจุบัน ณ เวลาที่มี SEGV กระบวนการที่ทำงานด้วยผู้ใช้และ / หรือกลุ่มที่มีประสิทธิภาพแตกต่างจากผู้ใช้จริง / กลุ่มจะไม่เขียนไฟล์หลัก
Darron

2

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

ทำไมถึงดีกว่า
Nathan Fellman

ไฟล์หลักที่สร้างขึ้นหลังจากความผิดพลาดไม่จำเป็นต้องulimit -c unlimitedอยู่ในสภาพแวดล้อมของบรรทัดคำสั่งจากนั้นรันแอปพลิเคชันอีกครั้ง
kgbook

ฉันไม่ต้องการให้มีการถ่ายโอนข้อมูลหลักทุกครั้งที่เกิดปัญหาเฉพาะเมื่อผู้ใช้ติดต่อฉันในฐานะนักพัฒนาเพื่อดูมัน หากเกิดปัญหา 100 ครั้งฉันไม่จำเป็นต้องทิ้งขยะ 100 คอร์เพื่อดู
Nathan Fellman

ulimit -c unlimitedในกรณีที่ท่าดีกว่าการใช้ นอกจากนี้คุณสามารถคอมไพล์ด้วยคำจำกัดความของ marco แอปพลิเคชันจะไม่รวมenable_core_dumpสัญลักษณ์หากไม่ได้กำหนดแมโครนั้นเมื่อวางจำหน่ายและคุณจะได้รับการถ่ายโอนข้อมูลหลักแทนที่ด้วยรุ่นดีบัก
kgbook

แม้ว่าจะผ่านการรับรองโดยแมโครแล้วก็ตามฉันยังต้องคอมไพล์อีกครั้งหากฉันต้องการสร้างคอร์ดัมพ์แทนที่จะใช้คำสั่งในเชลล์ก่อนเรียกใช้ซ้ำ
Nathan Fellman

1

เป็นมูลค่าการกล่าวขวัญว่าถ้าคุณมีการตั้งค่าsystemdแล้วสิ่งที่แตกต่างกันเล็กน้อย ที่กำหนดขึ้นโดยทั่วไปแล้วจะมีไฟล์หลักได้รับการประปาโดยใช้วิธีการcore_patternค่า sysctl systemd-coredump(8)ผ่าน โดยทั่วไปขนาดไฟล์หลักจะกำหนดค่าเป็น "ไม่ จำกัด " อยู่แล้ว

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

0

Ubuntu 19.04

คำตอบอื่น ๆ ทั้งหมดนั้นไม่ได้ช่วยฉัน แต่ข้อสรุปต่อไปนี้ทำงานได้

สร้าง~/.config/apport/settingsด้วยเนื้อหาต่อไปนี้:

[main]
unpackaged=true

(สิ่งนี้บอกให้ apport เขียน core ทิ้งสำหรับแอพที่กำหนดเอง)

ตรวจสอบ: ulimit -c. ถ้ามันออก 0 แก้ไขด้วย

ulimit -c unlimited

สำหรับในกรณีที่เริ่ม apport ใหม่:

sudo systemctl restart apport

/var/crash/ไฟล์ผิดพลาดจะถูกเขียนอยู่ในขณะนี้ แต่คุณไม่สามารถใช้กับ gdb ได้ หากต้องการใช้กับ gdb ให้ใช้

apport-unpack <location_of_report> <target_directory>

ข้อมูลเพิ่มเติม:

  • core_patternคำตอบบางอย่างขอแนะนำให้เปลี่ยน โปรดระวังว่าไฟล์ดังกล่าวอาจถูกเขียนทับโดยบริการ apport เมื่อทำการรีสตาร์ท
  • เพียงแค่หยุด apport ไม่ได้ทำงาน
  • ulimit -cค่าอาจจะได้รับการเปลี่ยนแปลงโดยอัตโนมัติในขณะที่คุณกำลังพยายามที่คำตอบอื่น ๆ ของเว็บ ตรวจสอบให้แน่ใจว่าได้ตรวจสอบอย่างสม่ำเสมอในระหว่างการตั้งค่าการสร้างการถ่ายโอนข้อมูลหลักของคุณ

อ้างอิง:

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.