ulimit -c unlimited只在当前终端生效,因其是per-process软限制,仅影响当前shell及其子进程,不继承至systemd服务、cron任务或非登录shell;永久生效需配置/etc/security/limits.conf、用户shell文件或systemd服务的LimitCORE=infinity。

ulimit -c unlimited 为什么只在当前终端生效
因为 ulimit -c 是 per-process 的软限制,只影响当前 shell 及其直接 fork 出的子进程。它不会继承到 systemd 服务、cron 任务、SSH 登录后的非登录 shell(比如用 ssh host command 方式执行),也不会跨会话保留。
常见误操作:
- 在桌面终端里执行了
ulimit -c unlimited,然后双击启动一个 GUI 程序 —— 它根本不会读这个设置 - 写了个脚本放进
/etc/cron.d/,发现崩溃没 core —— cron daemon 自己的 ulimit 是独立的 - 用
systemctl start myapp.service启动,结果没 core —— 必须在 unit 文件里加LimitCORE=infinity
验证是否真生效:在目标环境下(比如你准备跑程序的那个终端或服务上下文)直接运行 ulimit -c,输出必须是 unlimited 或一个正整数。
/proc/sys/kernel/core_pattern 路径不生效的三个硬性条件
内核写 core 文件前会做三道检查,缺一不可:
- 目标路径的**父目录必须已存在**,且权限为
1777(即 sticky bit + rwx for all)。例如设成/var/crash/core.%e.%p.%t,就得提前mkdir -p /var/crash && chmod 1777 /var/crash;755或775都不行 - 如果
core_pattern以|开头(如|/usr/lib/systemd/systemd-coredump %P %u),说明走用户态处理器,此时必须确保对应二进制可执行、有权限、且服务已启用:systemctl is-active systemd-coredump应返回active -
fs.suid_dumpable默认是0,导致sudo、passwd这类 setuid 程序即使 ulimit 允许也拒绝 dump —— 必须显式设为2:echo 2 | sudo tee /proc/sys/fs/suid_dumpable
systemd 服务怎么开 core dump
systemd 的资源限制完全隔离于用户 shell,改 ulimit 或 /etc/security/limits.conf 对它无效。
正确做法是编辑服务的覆盖配置:
- 运行
sudo systemctl edit myapp.service - 填入:
[Service] LimitCORE=infinity # 如果程序用了大页内存或 memlock,可能还需: MemoryLimit=infinity LockPages=false
然后重载并重启:sudo systemctl daemon-reload && sudo systemctl restart myapp.service
注意:有些发行版(如 RHEL 8+)默认禁用 LimitCORE,即使写了 infinity 也要确认 systemctl show myapp.service | grep LimitCORE 输出确实是 infinity,而不是 fallback 到 0。
core 文件生成了但 gdb 报 “No symbol table” 或内容为空
这不是配置失败,而是两个不同层面的问题:
-
No symbol table:说明可执行文件编译时没加-g,或者调试符号被 strip 掉了。解决方法是用带调试信息的原二进制文件重试,别用strip过的版本 - core 文件为空或只有几 KB:先用
file core确认是不是合法 ELF;再查readelf -l core | grep LOAD,对比原 binary 的 segment 数量 —— 如果明显更少,可能是程序自己标记了某些 VMA 为VM_DONTDUMP(比如用了madvise(..., MADV_DONTDUMP)),这是程序行为,不是系统配置问题 - 如果
core_pattern指向管道,还要看/proc/sys/kernel/core_pipe_limit,设成1会导致并发 crash 时丢 dump
最易忽略的一点:core 文件名里的 %e 是取 argv[0],不是磁盘上可执行文件的路径名。如果你用 ./myapp 启动,%e 就是 myapp,不是 ./myapp 或 /home/user/myapp —— 所以用 gdb 时得手动指定完整路径。


















