Linux下开启coredump转储以及生成core文件的配置

C/C++开发过程中经常会使用到gdb调试,而coredump作为程序发生崩溃或异常终止时生成的一种文件,包含了程序在崩溃时内存的快照和其他信息,能够让我们第一时间内快速开始排查错误发生的原因。而默认情况下,Linux是关闭了coredump转储文件的生成,毕竟开启这个功能,会产生一定的系统开销。

1、开启coredump转储以及core文件生成

可以通过如下命令ulimit -c查看系统能否生成coredump

1
2
ubuntu@VM-20-15-ubuntu:~$ ulimit -c
0

0表示不会生成,可以通过下面的命令设置core 文件的大小:

  • 生成不受限的core文件
1
2
3
ubuntu@VM-20-15-ubuntu:~$ ulimit -c unlimited # 表示生成的core文件大小不受限制
ubuntu@VM-20-15-ubuntu:~$ ulimit -c
unlimited
  • 生成受限大小的core文件
1
2
3
ubuntu@VM-20-15-ubuntu:~$ ulimit -c 2048 # 表示生成core文件大小被限制为2048K
ubuntu@VM-20-15-ubuntu:~$ ulimit -c
2048

以上的配置都只是临时开启的,当系统重启或者是用户重新登录便会失效,所以若要永久开启coredump转储,需要修改配置文件/etc/security/limits.conf,增加如下项:

1
*               soft    core            unlimited

该项表示设置core文件的大小为unlimited,如果想要设置具体的文件大小,也可以改为具体的数值。

修改成功后,重新登录用户并执行ulimit -c命令就可以看到修改已经起作用了。

2、配置core的文件名以及生成位置

网上的一些文章提到:

coredumpcore文件默认生成路径可以通过修改 /proc/sys/kernel/core_pattern 文件来自定义。

但在ubuntu系统下,执行more /proc/sys/kernel/core_pattern显示的是如下内容:

1
2
ubuntu@VM-20-15-ubuntu:~/c_cpp_code/test_01$ cat /proc/sys/kernel/core_pattern
|/usr/share/apport/apport %p %s %c %d %P %E

其中的|/usr/share/apport/apport是一个脚本(用于自动错误报告的工具),它利用%p %s %c %d %P %E这些参数来生成core文件以及文件名,这些参数的具体意义如下:

  • %p:进程ID(Process ID),表示崩溃的应用程序的进程ID。
  • %s:信号(Signal),表示导致崩溃的信号。
  • %c:核心转储文件(Core Dump File),表示核心转储文件的路径。
  • %d:日期(Date),表示崩溃发生的日期和时间。
  • %p:包名(Package Name),表示崩溃的应用程序所属的软件包的名称。
  • %E:执行命令(Executable Path),表示崩溃的应用程序的可执行文件路径。

进一步地,我们可以简单地看一下core文件的默认名称是什么:

image-20240407161633736

可以看到,它应该默认是生成于可执行文件所在的目录下以及名称是core。在这种设置下,新生成的core文件会覆盖旧的core文件,如果我们需要某一时刻下的core文件时,就比较麻烦。

core文件的参数格式:

参数 意义
%% 符号%
%p 进程号
%u 进程用户id
%g 进程用户组id
%s 生成core文件时收到的信号
%t 生成core文件的时间戳(seconds since 0:00h, 1 Jan 1970)
%h 主机名
%e 程序文件名

要让core文件带有pid,需要配置/proc/sys/kernel/core_uses_pid的内容为1,执行如下命令进行配置:

1
2
3
root@VM-20-15-ubuntu:~# echo -e "1" > /proc/sys/kernel/core_uses_pid # 需要在root用户下操作
root@VM-20-15-ubuntu:~# cat /proc/sys/kernel/core_uses_pid
1

指定生成的core文件在指定目录下,并按照一定的格式命名core文件:

1
2
3
4
root@VM-20-15-ubuntu:~# mkdir /dump # 改目录名可以按照自己需求来改
root@VM-20-15-ubuntu:/# chmod 777 /dump # 赋予777权限
root@VM-20-15-ubuntu:~# echo -e "\nkernel.core_pattern=/dump/core-%e-%s-%u-%g-%p-%t" >> /etc/sysctl.conf
root@VM-20-15-ubuntu:/# sysctl -p /etc/sysctl.conf

需要注意的是:由于/proc目录是动态更新的,系统会初始化core_pattern文件的值,所以直接修改/proc/sys/kernel/core_pattern是无法永久地指定core文件生成到指定的目录下的,所以需要按照上面的配置来修改才能永久的起作用。

3、测试生成的core文件

简单地写了如下的demo程序:

1
2
3
4
5
6
7
8
9
10
11
#include<iostream>
int foo(int a){
int* ptr;
*ptr = a;
return *ptr;
}
int main()
{
foo(100);
return 0;
}

使用g++编译一下(不带-g参数也可以的):

1
g++ main.cpp -o main

执行该程序后,由于存在野指针,会提示发生段错误:

1
2
ubuntu@VM-20-15-ubuntu:~/c_cpp_code/test_01$ ./main
Segmentation fault (core dumped)

这时就可以从/dump目录下看到对应的core文件,并且可以根据该core文件进行调试了:

image-20240407173220610

4、参考文章

  1. 让golang程序生成coredump文件并进行调试 - apocelipes - 博客园 (cnblogs.com)
  2. linux下生成core dump方法与gdb解析core dump文件_linux 下生产core dump方法 与gdb解析core dump文件-CSDN博客
  3. CentOS开启coredump转储并生成core文件的配置 - TypeCodes

Linux下开启coredump转储以及生成core文件的配置
http://1291945816.github.io/2024/04/07/Linux下开启coredump转储以及生成core文件的配置/
作者
Hps
发布于
2024年4月7日
更新于
2024年4月7日
许可协议