必须使用绝对路径配置 kernel.core_pattern,否则守护进程因工作目录不可写导致转储失败;需确保目录存在、权限正确、禁用 PrivateTmp、调整 fs.suid_dumpable 和 ptrace_scope 等安全参数。

kernel.core_pattern 配置项必须用绝对路径
Linux 内核转储路径由 /proc/sys/kernel/core_pattern 控制,它不是普通文件系统路径,而是一个内核参数。如果写成相对路径(如 core 或 ./core.%p),内核会在进程当前工作目录下尝试写入——但多数守护进程工作目录是 / 或不可写目录,导致转储失败且无日志提示。
正确做法是始终使用绝对路径,并确保目标目录存在、有写权限、且挂载时未启用 noexec 或 nosuid(虽然不影响写 core,但某些安全策略会限制):
echo "/var/crash/core.%e.%p.%t" > /proc/sys/kernel/core_pattern- 创建目录:
mkdir -p /var/crash && chmod 1777 /var/crash(1777允许所有用户写但只能删自己文件) - 永久生效需写入
/etc/sysctl.conf:kernel.core_pattern = /var/crash/core.%e.%p.%t
core_pattern 中的 % 占位符不能随意组合
内核只识别特定格式化符号,拼错或多余字符会导致整个 pattern 被当作普通文件名(即生成名为 core.%e.%p.%x 的静态文件,而非带替换的动态文件)。常见有效占位符有:
-
%e:可执行文件名(不含路径) -
%p:崩溃进程 PID -
%t:UNIX 时间戳(秒级) -
%u:真实 UID -
%%:字面量 % 符号
无效示例:core.%E(大写 E 不支持)、core.%pid(非标准写法)、core.%h(无此变量)。建议用 cat /proc/sys/kernel/core_pattern 确认当前值是否被 shell 解析过——若含未转义的 $ 或反引号,说明被 shell 展开了,这是错误的。
systemd 环境下需额外禁用 PrivateTmp 干扰
启用 PrivateTmp=yes 的 systemd service(如 nginx、httpd)会在崩溃时把 core dump 写进临时命名空间的 /tmp 目录,该目录在服务退出后立即销毁,导致 core 文件“消失”。即使 core_pattern 指向 /var/crash,也仍可能因 RestrictAddressFamilies 或 ProtectSystem 导致写入失败。
验证方式:systemctl show <service-name> | grep -E "(PrivateTmp|CoreDump)"</service-name>。若需保留 core dump,应在 service 单元中显式设置:
-
CoreDumpFilter=0xffffffff(允许完整内存映射转储) -
PrivateTmp=no(避免 tmp 隔离干扰路径解析) -
LimitCORE=infinity(解除 ulimit 限制)
改完后重载:systemctl daemon-reload && systemctl restart <service-name></service-name>。
调试时别忽略 fs.suid_dumpable 和 ptrace_scope
两个关键安全参数会直接拦截 core dump 生成,且不报错:
-
fs.suid_dumpable = 0(默认值):任何 setuid 程序崩溃都不会生成 core,即使 root 运行。调试时需临时设为1:sysctl -w fs.suid_dumpable=1 -
kernel.yama.ptrace_scope = 1(常见于 Ubuntu/Debian):阻止非子进程对进程做 ptrace,间接导致部分 crash handler(如 ABRT)无法捕获 dump。设为0可放宽限制
注意:ptrace_scope 改动影响调试安全性,生产环境勿长期开启;suid_dumpable 设为 1 后,务必确认没有敏感 setuid 程序暴露风险。
路径配置本身很简单,难的是让内核真正把 core 写进去——权限、命名空间、安全模块、进程上下文,四层过滤缺一不可。漏掉任意一层,core_pattern 就只是个摆设。


















