ฉันมีกระบวนการใน Linux ที่ได้รับการแบ่งกลุ่มผิดพลาด ฉันจะบอกให้สร้างคอร์ดัมพ์เมื่อมันล้มเหลวได้อย่างไร
ฉันมีกระบวนการใน Linux ที่ได้รับการแบ่งกลุ่มผิดพลาด ฉันจะบอกให้สร้างคอร์ดัมพ์เมื่อมันล้มเหลวได้อย่างไร
คำตอบ:
ขึ้นอยู่กับว่าคุณใช้เชลล์อะไร หากคุณกำลังใช้ bash คำสั่ง ulimit จะควบคุมการตั้งค่าต่าง ๆ ที่เกี่ยวข้องกับการทำงานของโปรแกรมเช่นว่าคุณควรถ่ายโอนข้อมูลหลักหรือไม่ ถ้าคุณพิมพ์
ulimit -c unlimited
จากนั้นจะบอกว่าทุบตีโปรแกรมของมันสามารถทิ้งแกนขนาดใดก็ได้ คุณสามารถระบุขนาดเช่น 52M แทนไม่ จำกัด หากคุณต้องการ แต่ในทางปฏิบัติสิ่งนี้ไม่จำเป็นเพราะขนาดของไฟล์หลักอาจไม่เป็นปัญหาสำหรับคุณ
ใน tcsh คุณจะต้องพิมพ์
limit coredumpsize unlimited
ดังที่อธิบายไว้ข้างต้นคำถามจริงที่ถูกถามที่นี่คือวิธีการเปิดใช้งานการถ่ายโอนข้อมูลหลักบนระบบที่ไม่ได้เปิดใช้งาน คำถามนั้นตอบที่นี่
หากคุณมาที่นี่โดยหวังที่จะเรียนรู้วิธีสร้างการถ่ายโอนข้อมูลหลักสำหรับกระบวนการที่หยุดทำงานคำตอบคือ
gcore <pid>
ถ้า gcore ไม่สามารถใช้ได้ในระบบของคุณแล้ว
kill -ABRT <pid>
อย่าใช้ kill -SEGV เนื่องจากมักจะเรียกตัวจัดการสัญญาณทำให้การวินิจฉัยกระบวนการที่ติดอยู่ยากขึ้น
-ABRT
จะเรียกใช้ตัวจัดการสัญญาณมากกว่า-SEGV
เนื่องจากการยกเลิกมีแนวโน้มที่จะกู้คืนได้มากกว่า segfault (ถ้าคุณจัดการ segfault ที่ปกติมันก็จะเรียกอีกครั้งทันทีที่ออกจากการจัดการของคุณ.) -QUIT
ทางเลือกที่ดีกว่าของสัญญาณสำหรับการสร้างถ่ายโอนข้อมูลหลักคือ
ในการตรวจสอบตำแหน่งที่ทิ้งขยะหลักให้สร้าง:
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 ทิ้งหลักจะถูกจัดการโดยApport/var/crash/
และสามารถอยู่ใน อย่างไรก็ตามจะถูกปิดใช้งานตามค่าเริ่มต้นในรุ่นที่เสถียร
สำหรับรายละเอียดเพิ่มเติมโปรดตรวจสอบ: ฉันจะหา core dump ใน Ubuntu ได้ที่ไหน? .
สำหรับ macOS โปรดดู: วิธีสร้างการถ่ายโอนข้อมูลหลักใน Mac OS X ได้อย่างไร
สิ่งที่ฉันทำในตอนท้ายคือการแนบ gdb กับกระบวนการก่อนที่มันจะผิดพลาดและเมื่อมันได้รับ segfault ฉันดำเนินการgenerate-core-file
คำสั่ง การบังคับให้สร้างแกนดัมพ์
ge
)
ulimit -c
ไปunlimited
แต่ไฟล์หลักคือการสร้างนิ่งไม่มีgenerate-core-file
แฟ้มในเซสชั่น gdb ไม่สร้างไฟล์หลักขอบคุณ
บางทีคุณสามารถทำได้ด้วยวิธีนี้โปรแกรมนี้เป็นการสาธิตวิธีดักจับการแบ่งเซกเมนต์และเชลล์ออกไปยังดีบั๊ก (นี่คือรหัสต้นฉบับที่ใช้ภายใต้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 หลักที่แสดงที่นี่ในบล็อกนี้ที่นี่
มีหลายสิ่งที่อาจมีผลต่อการสร้างดัมพ์หลัก ฉันพบสิ่งเหล่านี้:
/proc/sys/kernel/core_pattern
แต่ที่อาจมีการเปลี่ยนแปลงโดยการตั้งค่า /proc/sys/fs/suid_dumpable
อาจป้องกันแกนที่จะสร้างมีสถานการณ์มากขึ้นซึ่งอาจป้องกันไม่ให้รุ่นที่อธิบายไว้ในหน้าคนมี - man core
ลอง
เพื่อเปิดใช้งานการถ่ายโอนข้อมูลหลักทำต่อไปนี้:
ใน /etc/profile
ความคิดเห็นบรรทัด:
# ulimit -S -c 0 > /dev/null 2>&1
ใน/etc/security/limits.conf
ความคิดเห็นออกสาย:
* soft core 0
ดำเนินการ 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
#
เพื่อตรวจสอบว่า corefile ได้รับการเขียนคุณสามารถฆ่ากระบวนการที่เกี่ยวข้องด้วย cmd kill -s SEGV <PID>
(ไม่จำเป็นต้องใช้ในกรณีที่ไม่มีไฟล์ core ที่เขียนสิ่งนี้สามารถใช้เป็นการตรวจสอบ):
# kill -s SEGV <PID>
เมื่อเขียน corefile แล้วให้ปิดการตั้งค่า coredump อีกครั้งในไฟล์ที่เกี่ยวข้อง (1./2./3)
สำหรับ Ubuntu 14.04
ตรวจสอบการถ่ายโอนข้อมูลหลักที่เปิดใช้งาน:
ulimit -a
หนึ่งในบรรทัดควรเป็น:
core file size (blocks, -c) unlimited
ถ้าไม่ :
gedit ~/.bashrc
และเพิ่มulimit -c unlimited
ที่ส่วนท้ายของไฟล์และบันทึกเรียกใช้เทอร์มินัลใหม่
สร้างแอปพลิเคชันของคุณด้วยข้อมูลแก้ไขข้อบกพร่อง:
ใน Makefile -O0 -g
เรียกใช้แอปพลิเคชันที่สร้าง core dump (ไฟล์ dump หลักที่มีชื่อ 'core' ควรสร้างใกล้กับไฟล์ application_name):
./application_name
ทำงานภายใต้ gdb:
gdb application_name core
ulimit -c unlimited
เทอร์มินัลสำหรับการแก้ปัญหาชั่วคราวเพราะการแก้ไขเฉพาะ~/.bashrc
ต้องการเทอร์มินัลสำหรับการเปลี่ยนแปลงที่จะทำให้เกิดผล
โดยค่าเริ่มต้นคุณจะได้รับไฟล์หลัก ตรวจสอบเพื่อดูว่าไดเรกทอรีปัจจุบันของกระบวนการสามารถเขียนได้หรือไม่มีไฟล์หลักที่จะถูกสร้างขึ้น
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));
}
ulimit -c unlimited
อยู่ในสภาพแวดล้อมของบรรทัดคำสั่งจากนั้นรันแอปพลิเคชันอีกครั้ง
ulimit -c unlimited
ในกรณีที่ท่าดีกว่าการใช้ นอกจากนี้คุณสามารถคอมไพล์ด้วยคำจำกัดความของ marco แอปพลิเคชันจะไม่รวมenable_core_dump
สัญลักษณ์หากไม่ได้กำหนดแมโครนั้นเมื่อวางจำหน่ายและคุณจะได้รับการถ่ายโอนข้อมูลหลักแทนที่ด้วยรุ่นดีบัก
เป็นมูลค่าการกล่าวขวัญว่าถ้าคุณมีการตั้งค่า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
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 เมื่อทำการรีสตาร์ทulimit -c
ค่าอาจจะได้รับการเปลี่ยนแปลงโดยอัตโนมัติในขณะที่คุณกำลังพยายามที่คำตอบอื่น ๆ ของเว็บ ตรวจสอบให้แน่ใจว่าได้ตรวจสอบอย่างสม่ำเสมอในระหว่างการตั้งค่าการสร้างการถ่ายโอนข้อมูลหลักของคุณอ้างอิง: