ulimit -c为0是最常见原因,表示进程启动时shell环境禁止生成core文件;需检查实际运行环境的/proc/PID/limits、systemd的LimitCORE配置、core_pattern、suid_dumpable及目录权限,并用kill -SEGV $$实测验证。

ulimit -c 为 0 是 core 文件消失的最常见原因
服务崩溃后找不到 core 文件,第一反应不是翻日志、不是重编译,而是立刻查 ulimit -c。输出是 0,就等于系统对这个进程下了“禁止留遗书”的命令——内核收到 SIGSEGV 等信号后,连文件句柄都不开,直接静默退出。
注意:这个限制作用于**进程启动时的 shell 环境**,不是全局开关。即使 root 用户在另一个终端里执行了 ulimit -c unlimited,也不会影响已启动的服务进程。
- 检查当前会话限制:
ulimit -c - 检查服务实际运行环境:
cat /proc/<pid>/limits | grep core</pid>(把<pid></pid>换成服务真实 PID) - 如果服务由 systemd 管理,
ulimit -c在服务单元中无效,必须改LimitCORE=配置项
systemd 服务绕过 ulimit -c 的典型陷阱
很多服务用 systemctl start xxx 启动,但它的资源限制和你登录终端完全隔离。即使你在 shell 里执行了 ulimit -c unlimited,systemd 子进程默认仍继承 LimitCORE=0(即等效于 ulimit -c 0)。
验证方式:systemctl show <service-name> | grep LimitCORE</service-name>。常见输出是 LimitCORE=0 或空值(表示未显式设置,按 systemd 默认策略为 0)。
- 临时生效(重启服务前):
sudo systemctl set-property <service-name> LimitCORE=infinity</service-name> - 永久生效:编辑服务单元文件,在
[Service]段下添加LimitCORE=infinity,然后sudo systemctl daemon-reload - 注意:
infinity是 systemd 的写法,不是unlimited;写错会静默忽略
确认崩溃发生但 core 仍没生成?重点查三个内核开关
崩溃信号确实发出了(dmesg | tail -20 能看到 segfault at ... ip ... sp ... error ...),但 core 还是没影——说明内核在 do_coredump() 链路上被拦住了。除了 ulimit -c,必须看:
-
cat /proc/sys/kernel/core_pattern:如果以|开头(如|/usr/lib/systemd/systemd-coredump %P %u %g %s %t %e),说明交由用户态程序处理,此时要查systemd-coredump是否启用:systemctl is-active systemd-coredump -
cat /proc/sys/fs/suid_dumpable:值为0时,任何setuid程序(比如用sudo启动或自身设了setuid位)都不会生成 core;需设为2才允许 -
cat /proc/sys/kernel/core_uses_pid:值为0时,所有 core 都叫core,容易被覆盖;设为1可避免混淆,但不解决生成失败问题
测试 core 是否真能落地,别信配置,要动手触发
改完所有配置,别急着等服务崩——用最简方式主动触发一次 SIGSEGV,验证整个链路是否打通:
在服务同用户、同环境下执行:kill -SEGV $$(向当前 shell 进程发段错误)。几秒后检查预设路径(如 /tmp/core.* 或 /var/coredump/)是否有新文件生成。
- 成功:说明配置已生效,下次服务崩溃就能拿到
core - 失败:回到上一步,逐个检查
/proc/sys/...三参数 +ulimit -c+ 目标目录权限(ls -ld /tmp/coredumps看是否可写) - 特别注意:Docker 容器内需加
--ulimit core=-1:-1参数,否则容器 runtime 会覆盖宿主机设置
真正难排查的不是“怎么开”,而是“谁关的”——可能是上线脚本里某行 ulimit -c 0,可能是 systemd 模板继承了旧基线配置,也可能是容器镜像构建时固化了限制。每次改完,务必用 kill -SEGV $$ 实锤验证,而不是靠 cat 出来的配置自我安慰。


















