当前位置:首页>Linux>Linux进程崩溃复盘:Coredump 开启与 GDB 分析

Linux进程崩溃复盘:Coredump 开启与 GDB 分析

  • 2026-10-11 07:31:16
Linux进程崩溃复盘:Coredump 开启与 GDB 分析

进程收到致命信号(如 SIGSEGV、SIGABRT)时,内核可写出内存快照(core)。配合 GDB 可回溯调用栈、查看变量,是定位段错误、空指针、断言失败的有效手段之一。

本文按 先查现状 → 再开启 → 配路径 → 分析 → 排坑 的顺序说明。


一、看当前coredump是否开启以及存储路径

ulimit -c               # 看当前这个 shell 里,进程允许生成的 core 文件大小上限ulimit -a               # 列出当前 shell 下各种资源的 soft 限制(文件数、栈大小、core 大小等)sysctl kernel.core_pattern    #读内核参数,看core写到哪里、叫什么名字,或是否交给别的程序处理cat /proc/sys/kernel/core_pattern # 看coredump路径# 若输出以 | 开头,说明由 systemd-coredump 等用户态程序接管systemctl status systemd-coredump 2>/dev/nullcoredumpctl list  #列出本机由 systemd-coredump 保存的历史 coredump 记录
ulimit -c
 值
含义

0

不生成 core

unlimited

不限制 core 大小

正整数

core 大小上限(单位依 shell/实现,常见为 1024 字节块,勿简单等同「字节」)


二、如何开启 Coredump

2.1 临时开启(仅当前 shell)

ulimit -c unlimited

关闭终端或退出 SSH 后失效。systemd 管理的服务不会继承当前 shell 的 ulimit。

2.2 永久开启:limits.conf

编辑 /etc/security/limits.conf

(语法:domain type item value,不是 shell 脚本,不能 source):

* soft core unlimited* hard core unlimited

仅对特定用户生效时,将 * 换成用户名(如 user1234)。

维度
常见误区
正确理解

文件性质

当成 shell 脚本,source 一下

键值对,由 PAM(pam_limits.so)解析

生效时机

改完当前终端立刻生效

需重新登录或 restart 目标服务

已运行进程

改配置后自动更新

不会变,必须新会话 / 新进程

与 ulimit

是一回事

ulimit 改当前 shell;limits.conf 改登录时的默认上限

修改后如何生效:

场景
操作

SSH 会话

断开重连

守护进程(nginx、自定义服务等)

systemctl restart <服务>

已在运行的旧进程

必须重启进程或重新登录

2.3 systemd 服务(更稳妥)

在 unit 中配置:

[Service]LimitCORE=infinitysystemctl daemon-reloadsystemctl restart <服务名>

查看是否生效:

systemctl show <服务名> -p LimitCORE

2.4 登录 Shell 兜底:/etc/profile(和2.2效果差不多,本人最喜欢,推荐)

在 /etc/profile 末尾追加

ulimit -c unlimited

需要新Shell终端生效。

2.5 代码里开启

/* 错误:ulimit 只作用于 system() 起的子 shell */system("ulimit -c unlimited");在 main() 最早处调用:#include<sys/resource.h>voidenable_core_dump(void){struct rlimit rl;rl.rlim_cur = RLIM_INFINITY;rl.rlim_max = RLIM_INFINITY;setrlimit(RLIMIT_CORE, &rl);}

进程的 soft limit 不能超过父进程或 systemd 设置的 hard limit。

2.6 开启core总览表

方式
谁读 / 谁执行
生效范围
何时生效
是否持久

当前终端

ulimit -c

当前 shell

仅本 shell + 其子进程

立即

否

/etc/profile

登录 shell 启动时

交互式登录 shell 及其子进程

下次登录 shell 启动时;当前终端、同次 SSH 新标签不自动变

是

limits.conf

PAM(pam_limits)

建立登录会话时的进程(SSH、su - 等)

重新登录 / su - 后;不改已跑进程

是

systemd

LimitCORE

systemd 起服务时

该 unit 管理的服务及其子进程

daemon-reload + restart 服务后

是

代码中设置

进程自己在 main 最早处

本进程 + 其子进程(受父级 hard 限制)

进程启动后立刻(调用那一刻)

否,每次启动都要执行;且不能超过父进程/systemd 的 hard limit


三、配置 Core 文件存放路径

由 kernel.core_pattern 决定写到哪里、叫什么名字。

3.1 永久配置

新建 /etc/sysctl.d/99-core.conf:

kernel.core_pattern = /var/core/core-%e-%p-%tsudo mkdir -p /var/coresudo chown <运行用户>:<组> /var/coresudo sysctl -p /etc/sysctl.d/99-core.conf

3.2 占位符速查

符号
含义

%e

可执行文件名(不含路径,最长约 15 字符)

%p

进程 PID

%t

崩溃时间戳(epoch 秒)

%s

信号编号

%h

主机名

%E

可执行文件完整路径(/ 替换为 !)

%c

崩溃进程的 core 软限制大小

若 core_pattern 为相对路径(如 core-%e-%p-%t),core 会写在进程当前工作目录;systemd 服务需对齐 WorkingDirectory。

3.3 临时改路径(重启后丢失,除非写入 sysctl 配置)

sudo sysctl -w kernel.core_pattern='/tmp/core-%e-%p'

四、查Coredump 存储路径

sysctl kernel.core_pattern# 或cat /proc/sys/kernel/core_pattern

4.1 传统落盘

示例 pattern:

/var/core/core-%e-%p-%t

文件出现在 /var/core/,名称类似 core-myapp-12345-1716633600。

4.2 systemd 接管

systemd 接管是指,进程崩溃时,内核不直接把 core 写成你磁盘上的某个文件,而是把 core 数据交给 systemd 自带的程序 systemd-coredump 去处理、保存,不一定出现在你配置的 /var/core/ 路径。

示例 pattern(以 | 开头):

|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h

磁盘上不一定有「一个完整路径的 core 文件」,使用:

coredumpctl listcoredumpctl info <PID>coredumpctl gdb <可执行文件> <PID>

五、用 GDB 分析 Core

gdb /path/to/binary /path/to/core-file

GDB 内常用命令:

bt # 调用栈bt full # 带局部变量info threads # 多线程frame 3print some_var

二进制需与崩溃时一致,且最好带 -g 调试符号;否则栈中可能只有地址,难以对应源码行号。

查看某进程是否允许产生 core:

cat /proc/<pid>/limits | grep -i "Max core file size"

六、没有看到 Core 时排查

现象
可能原因
处理

完全没有 core

ulimit -c 为 0

ulimit -c unlimited 或 LimitCORE=infinity

完全没有 core

被 systemd-coredump 接管

coredumpctl list

有信号、无文件

core 目录不可写

检查 owner/权限

有信号、无文件

磁盘满

df -h

GDB 只有地址

无调试符号

Debug 构建或保留未 strip 二进制

SaveCoreDump 失败

core 不在 CWD

对齐 core_pattern 与 WorkingDirectory


七、禁用core

不需要 core 时:

ulimit -c 0或在 limits.conf / systemd 中设置 LimitCORE=0。

八、部署检查清单

sysctl kernel.core_patternsystemctl show <可执行文件名> -p LimitCOREsystemctl status coredump-cleanup.timerulimit -c # 在运行服务的用户会话下执行

异常链路中 handler_node 已注册 coredump → SaveCoreDump 动作;崩溃后除手动 GDB,也可在异常上报流程里自动归档 core。


结语

开启 Coredump 并不复杂,容易踩坑的是三层配置要对齐:

  1. ulimit / LimitCORE — 能不能写
  2. core_pattern — 写到哪里
  3. 进程 CWD / 业务代码 — 能不能被自动收集

把这三层对齐,再配合 -g 编译和 GDB,就可以通过coredump来看bug现场。

最新文章

随机文章