Go程序崩溃默认不生成core dump,因其panic机制不依赖信号触发内核dump流程;需显式调用syscall.Setrlimit启用,且仅对非Go原生panic(如Cgo abort、SIGSEGV)有效。

Go程序崩溃时没有core dump?默认不生成
Go运行时默认禁用系统级core dump,哪怕触发panic并导致进程退出,也不会自动生成core文件。这不是bug,是设计选择:Go的panic走的是自己的栈展开机制,不依赖信号(如SIGABRT)触发内核dump流程。
常见错误现象:ulimit -c unlimited设了、程序段错误了,但目录下就是没core文件;用gdb ./myapp core打不开——因为压根没生成。
- 必须显式启用:在启动前设置
syscall.Setrlimit(syscall.RLIMIT_CORE, &syscall.Rlimit{Cur: ^uint64(0), Max: ^uint64(0)}) - 仅对**非Go原生panic**有效:比如Cgo调用中触发
abort()、内存越界被内核kill(SIGSEGV)、或手动raise(SIGABRT) - Go原生
panic仍不会生成core——它不发信号,只调用runtime.fatalpanic - Linux下还需确认
/proc/sys/kernel/core_pattern没被重定向到systemd-coredump等接管器,否则文件可能出现在/var/lib/systemd/coredump/
想用gdb看Go panic现场?别指望core,改用pprof+trace
Go的panic现场无法通过gdb加载core分析,因为goroutine栈不在C栈上,且堆布局、调度器状态gdb看不懂。硬要gdb进core,看到的只是runtime.sigtramp或空栈帧。
真正有效的替代路径是运行时采集:
立即学习“go语言免费学习笔记(深入)”;
- 启动时加
-gcflags="all=-l"关闭内联,让符号更完整 - 暴露
/debug/pprof/goroutine?debug=2获取全goroutine栈快照(含panic前状态) - 用
runtime.SetTraceback("system")提升panic输出级别,显示更多寄存器和栈指针值 - 关键位置插入
runtime.Stack(buf, true)捕获当前所有goroutine栈到日志
示例:在init()里加runtime.SetTraceback("crash"),panic时会打印每个goroutine的PC、SP、函数名,比默认多出10倍上下文。
CGO_ENABLED=0时core dump完全失效?不是,但限制变多
当禁用CGO(CGO_ENABLED=0),Go程序彻底脱离libc,setrlimit调用不可用,ulimit -c设置也无效——此时连SIGSEGV都不会触发core dump,内核直接静默终止。
使用场景很典型:纯静态编译的CLI工具、容器镜像精简版、某些安全沙箱环境。
- 唯一办法:编译时加
-ldflags="-linkmode external -extld gcc"强制走外部链接器,保留libc调用能力 - 但会引入glibc依赖,破坏纯静态目标;Docker Alpine镜像里还得装
libc6-compat - 更现实的做法:接受无core事实,改用
go tool trace录制运行期事件,在panic前5秒内回溯调度、GC、阻塞点 - 注意:
go tool trace需提前开启,且只记录最后约5MB事件,高频panic容易覆盖关键片段
生产环境开core dump有风险?重点不是磁盘,是敏感信息泄露
很多人担心core dump占磁盘,其实更危险的是它会把整个进程内存镜像写入磁盘——包括TLS私钥、数据库密码、用户token、未加密的API响应体,全都明文躺在core文件里。
- Linux下用
echo 2 > /proc/sys/kernel/core_pattern可启用core.<pid></pid>命名,避免覆盖,但不解决内容问题 - 真正可控的方式:用
prctl(PR_SET_DUMPABLE, 0)在main开头禁用dump(需CGO),或用security.capabilities移除CAP_SYS_PTRACE - 若必须保留core,应配合
coredump_filter(/proc/self/coredump_filter)过滤掉匿名映射页(bit 0x10),大幅减少敏感数据量 - 容器环境建议:直接在
securityContext里设allowPrivilegeEscalation: false,从内核层禁掉dump能力
真正难排查的永远不是“怎么生成core”,而是“panic前最后一毫秒,哪个goroutine在读哪块内存、锁了什么、刚收到了什么channel消息”——这些信息core给不了,得靠日志埋点和运行时trace协同。










