core dump 概念
core dump
文件实际上是进程在某个时间点时的内存映像,当时进程使用的内存是啥样就会被原样保存下来存在文件系统的某个位置上,这个时间点一般是触发了SIGSEGV
或者SIGABRT
这两个信号的时候,当进程的内存映像保存完毕后进程就会异常终止,也就是大家喜闻乐见的“程序崩了”和“段错误:核心已转储”。
因此 coredump
就像是程序出错崩溃后的“第一现场”,是用来排查错误的主要资源。
golang 程序生成 coredump 方法
设置环境变量和在代码里调用相关的标准库接口
在这之前先用ulimit命令检测下系统当前能不能生成coredump:
|
|
如果是unlimited就表示可以,如果是0那就不会生成,需要修改ulimit的设置。
修改GOTRACEBACK环境变量
GOTRACEBACK
是用来控制panic发生时golang程序行为的,值是字符串,具体内容如下:
值 | 行为 |
---|---|
none | 不打印任何堆栈跟踪信息,不过崩溃的原因和哪行代码触发的panic还是会打印 |
single | 只打印当前正在运行的触发panic的goroutine的堆栈以及runtime的堆栈;如果panic是runtime里发出的,则打印所有goroutine的堆栈跟踪信息 |
all | 打印所有用户创建的goroutine的堆栈信息(不包含runtime的) |
system | 在前面all 的基础上把runtime相关的所有协程的堆栈信息也一起打印出来 |
crash | 打印的内容和前面system 一样,但还会额外生成对应操作系统上的 coredump 文件 |
将这个环境变量设置成crash
就可以获得信息最全面的coredump文件。
设置编译参数
|
|
|
|
运行程序生成 coredump
临时修改
|
|
永久修改(设置环境变量)
|
|
修改core dump文件路径
ps: 如果是容器启动的程序,可设置挂载卷将coredump生成到挂载目录中,这样就可以防止程序panic,容器退出丢失 coredump 文件
默认路径
|
|
临时修改
修改 /proc/sys/kernel/core_pattern
文件,但/proc
目录本身是动态加载的,每次系统重启都会重新加载,因此这种方法只能作为临时修改。例如:
|
|
永久修改
使用 sysctl -w name=value 命令。例如:
|
|
另外,为了更详尽的记录core dump当时的系统状态,可通过以下参数来丰富core文件的命名:
|
|
调试 coredump 文件
上述步骤会在获取到的 coredump 文件,使用 dlv(golang debug工具)调试。
dlv 安装
go 版本在1.6之前
|
|
1.6之后的版本
|
|
开始调试
按下面的步骤查看信息:
bt
,查看当前的调用堆栈,找到触发panic的那行代码在哪个frame(栈帧)里- 看到是编号为10的frame,使用
frame 10
进入这个栈帧 - 使用
locals
查看当前栈帧内变量的值 p <变量名/表达式>
查看变量的具体内容,或者执行一些简单的表达式- 还可以修改变量的值,设置断点后再次运行查看结果,不过例子里的问题到第四步就已经明了了。(数组索引为10,越界访问)