ulimit -c 返回 0 表示当前 shell 禁止生成 core 文件,需执行 ulimit -c unlimited 临时启用,或在 ~/.bashrc、/etc/security/limits.conf 中配置永久生效,systemd 服务还需单独设置 LimitCORE=infinity。

ulimit -c 返回 0 就说明被禁了
这是最常见、也最容易漏掉的原因。ulimit -c 输出 0 表示当前 shell 及其子进程完全禁止生成 core 文件,哪怕程序真的崩溃了,内核也会直接跳过 dump 步骤。
临时修复很简单:ulimit -c unlimited;但要注意它只对当前终端生效。新开一个终端,ulimit -c 又会变回 0。
永久生效得改配置:
- 用户级:在
~/.bashrc或~/.zshrc末尾加一行ulimit -c unlimited,然后source ~/.bashrc - 系统级:在
/etc/security/limits.conf里加两行:* soft core unlimited和* hard core unlimited,需重新登录才生效
注意:systemd 启动的服务(比如用 systemctl start myapp 跑的)完全不读 shell 的 ulimit,必须单独在 service unit 文件里写 LimitCORE=infinity。
/proc/sys/kernel/core_pattern 目录不存在或权限不对
core_pattern 决定了 core 文件写到哪、叫什么名。如果它指向一个目录(比如 /var/crash/core.%e.%p.%t),而该目录不存在,或者权限不是 1777,内核会静默放弃写入——你连错误提示都看不到。
检查当前设置:cat /proc/sys/kernel/core_pattern。默认是 core,意味着只往当前工作目录写,极易被覆盖或找不到。
修复步骤:
- 先确认目标路径存在:
sudo mkdir -p /var/crash - 设对权限:
sudo chmod 1777 /var/crash(777不够,必须带 sticky bit) - 临时改路径:
echo '/var/crash/core.%e.%p.%t' | sudo tee /proc/sys/kernel/core_pattern - 永久生效:往
/etc/sysctl.conf加kernel.core_pattern=/var/crash/core.%e.%p.%t,再sudo sysctl -p
setuid 程序崩溃却不生成 core?看 fs.suid_dumpable
普通程序开了 ulimit 就能 dump,但 sudo、passwd 这类 setuid 程序可能依然静默失败。问题常卡在内核开关 fs.suid_dumpable 上。
查当前值:cat /proc/sys/fs/suid_dumpable。很多发行版(如 RHEL 8+/CentOS Stream)默认是 0,即禁止所有 setuid 程序生成 core。
临时放开:sudo sysctl -w fs.suid_dumpable=2(2 表示允许)
永久配置:在 /etc/sysctl.conf 加 fs.suid_dumpable=2,再 sudo sysctl -p
注意:这个值设为 0 是安全加固手段,生产环境改之前得评估风险。
gdb 报 “No symbol table is loaded” 怎么办
这不代表 core 没生成,而是你用的可执行文件没带调试信息。gdb ./myapp core.1234 能进 gdb,但 bt 只显示地址、没函数名和行号,基本等于白忙。
编译时必须加 -g:
g++ -g -o myapp myapp.cpp- 如果是 release 构建,至少保留
-g,别用-s或strip去符号 - 用
file myapp检查:输出里有with debug_info才算合格
另外,core 文件本身是二进制快照,不依赖源码;但 gdb 需要可执行文件提供符号表和 DWARF 信息——两者缺一不可。
真正难排查的是多层限制叠加:shell 的 ulimit、systemd 的 LimitCORE、core_pattern 路径权限、suid_dumpable、甚至容器里没挂载 /proc/sys —— 它们像一串保险丝,断一根,core 就消失。动手前先逐项验证,别只盯着 gdb 报错。


















