1. 概述
应用程序在收到某些信号(man core
和man 7 signal
查看)的导致进程终止并生成核心转储文件(Coredump),即包含进程映像的磁盘文件终止时的内存(内存快照)。
这个内存映像快照可以被 debugger(GDB)调试工具用于分析进程终止原因,内存映像文件大小可以通过RLIMIT_CORE
进行设置;
比如常见的Ctrl+\
即(kill -QUIT PID
) 或 kill -ABRT PID
都会导致 CoreDump,相关参考man core
1.1. 导致生成 Coredump 的信号
|
|
1.2. 导致无法启用 core dump 机制
- 进程没有写核心文件或目录权限(默认核心文件称为 core,并在当前工作目录中创建)
- 存在相同的文件,但不可写,或者磁盘、inode、只读问题导致无法正常生成 core dump
- 进程的
RLIMIT_CORE
或者RLIMIT_FSIZE
设置为 0,见下文(getrlimit
和ulimit
)
1.3. 命名 - /proc/sys/kernel/core_pattern
导出的 core dump 文件名称默认为 core(cat /proc/sys/kernel/core_pattern
可见),可以通过下述参数修改:
|
|
ps: linux2.4 还可以通过/proc/sys/kernel/core_uses_pid
启用修改,默认生产类似core.PID
的转存储文件;
1.4. 管道转发 core dump 文件
从 linux2.6.19,若/proc/sys/kernel/core_pattern
首个字符是管道符号|
,则后续基于程序处理,而非写到磁盘;
1.5. 控制哪些内存映射内容导出到 core dump 文件
基于特定的 pid 文件,/proc/PID/coredump_filter
,配置内容:
|
|
coredump_filter 的默认值为0x3
,这反映了传统的 Linux 行为,这意味着只转储匿名内存段。
2. 开启 CoreDump 相关配置
2.1. 检测资源限制问题
ulimit -c
,0 表示不產生core dump
,所以要先執行ulimit -c unlimited
允許產生 core dump。
|
|
2.2. 指定 core dump 文件命名格式
|
|
2.3. 可以基于 gdb 调试和查看生成的 coredump 文件
#include <stdio.h>
int main() {
int *ptr = NULL; // NULL pointer.
*ptr = 100;
printf("%s", "SW-VERSION=0.1");
return 0;
}
// 编译
gcc abc.c
// 运行
[root@gearbest-web01-test_10 coredump-test]# ./a.out
段错误 (core dumped)
[New Thread 9285]
Core was generated by `./a.out'.
Program terminated with signal 11, Segmentation fault.
#0 0x0000000000400506 in ?? ()
"/root/coredump-test/core.a.out.9285.1569493778" is a core file.
Please specify an executable to debug.
...
3. 基于管道转到特定进程处理 coredump 内容(可忽略)
该处理流程是通过管道转发到特定程序处理后的结果,而非原本的 coredump 信息,这点需要处理,如果想重现所有内存信息,还是建议存储所有的 coredump 内存信息内容
3.1. coredump 命名配置
|
|
3.2. 处理脚本编译
/* core_pattern_pipe_test.c */
#define _GNU_SOURCE
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_SIZE 1024
int main(int argc, char *argv[]) {
int tot, j;
ssize_t nread;
char buf[BUF_SIZE];
FILE *fp;
char cwd[PATH_MAX];
/* Change our current working directory to that of the
crashing process */
snprintf(cwd, PATH_MAX, "/proc/%s/cwd", argv[1]);
chdir(cwd);
/* Write output to file "core.info" in that directory */
fp = fopen("core.info", "w+");
if (fp == NULL)
exit(EXIT_FAILURE);
/* Display command-line arguments given to core_pattern
pipe program */
fprintf(fp, "argc=%d\n", argc);
for (j = 0; j < argc; j++)
fprintf(fp, "argc[%d]=<%s>\n", j, argv[j]);
/* Count bytes in standard input (the core dump) */
tot = 0;
while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
tot += nread;
fprintf(fp, "Total bytes in core dump: %d\n", tot);
exit(EXIT_SUCCESS);
}
// 编译
cc -o core_pattern_pipe_test core_pattern_pipe_test.c
// 通过Ctrl+\信号退出,产生coredump
[root@gearbest-web01-test_10 coredump-test]# sleep 10
^\退出 (core dumped)
// 查看core.info文件(通过我们的c程序处理脚本生成)
[root@gearbest-web01-test_10 coredump-test]# cat core.info
argc=5
argc[0]=</root/coredump-test/core_pattern_pipe_test>
argc[1]=<1631>
argc[2]=<UID=0>
argc[3]=<GID=0>
argc[4]=<sig=3>
Total bytes in core dump: 319488
4. 应用场景
在执行应用进程,尤其是常驻服务,可能存在内存泄露的引用 OOM,但无法知道具体是由于什么问题引起,包括应用内存使用情况,可以考虑采用 CoreDump 分析问题;
另外一些应用导致异常终止,比较段错误、越界、浮点异常等,若应用没有对应的处理,也会导致问题很难复现,此时可以通过记录 coredump 来复现故障前的内存快照来进行分析(之前就发现 PHP 的 OOM 问题,是由于读取大量 Excel 文件导致)