Golang 程序 crash 的时候自动 core dump

前段时间遇到一个问题,程序莫名其妙 crash 了,stack 也没看出什么端倪来。今天改了一个参数,让 golang 程序在崩溃的时候 core dump。

其实核心就是加一个环境变量就可以了,GOTRACEBACK=1. 但是还有一些其他跟系统相关的问题,这篇文章简单记录一下。

Golang 1.6 之后,这个环境的变量可选值有了一些变化,新的值如下:

  • GOTRACEBACK=none will suppress all tracebacks, you only get the panic message.
  • GOTRACEBACK=single is the new default behaviour that prints only the goroutine believed to have caused the panic.
  • GOTRACEBACK=all causes stack traces for all goroutines to be shown, but stack frames related to the runtime are suppressed.
  • GOTRACEBACK=system is the same as the previous value, but frames related to the runtime are also shown, this will reveal goroutines started by the runtime itself.
  • GOTRACEBACK=crash is unchanged from Go 1.5.

一些要注意的点:

首先,介绍下除了这个 GOTRACEBACK 参数,还有其他一些很有用的能控制 golang 运行时的环境变量,这篇文章总结的很好。

然后这个参数在 macOS 上是无效的,就不要在 MAC 上白费力气了。

Linux 上还受到 ulimit 的限制。可以用 ulimit -c 查看对 Core dump 的大小限制。如果是 0 是 dump 不出来了,也不建议设置成 ulimited。我改成了 50G。如果程序使用 systemd 启动的,可以设置 service unit 文件中的 LimitCORE= 参数,效果等同。

产生的 core dump 存放在哪里了呢?

可以通过这里查看:

这里定义了 core dump 文件的命名方式。

但是在 ubuntu 里面,会看到这样的输出:

意思是通过 pipe 定向到了 apport. apport 是 ubuntu 发行版选择使用的 core dump 管理服务。

默认情况下,用户程序是不会有 core dump 的。然后我们有两个解决办法:

  1. 关闭 apport,使用系统的 core dump 直接写在磁盘上
  2. 配置 apport,让它也写用户的 core dump 文件

第一种方法比较简单,直接修改上文中的 /proc/sys/kernel/core_pattern 文件即可:

注意这里有一个小小的问题要注意一下:这个配置是全局的,只有 root 账户才能编辑。如果在普通用户下执行 sudo echo "kernel.core_pattern=/tmp/%e.%t.%p.%s.core" > /proc/sys/kernel/core_pattern 是不行的,因为在这行命令中,echo 是用 sudo 执行的,但是重定向确实 shell (bash) 来完成的,重定向,即真正的写入工作,实际上没有在 root 下,所以你会得到错误:Permission denied, 或者 Destination /proc/sys/kernel not writable. 解决办法是用这个命令:sudo bash -c 'echo "kernel.core_pattern=/tmp/%e.%t.%p.%s.core" > /proc/sys/kernel/core_pattern'.

然后可以 disable apport:

 

第二种方法,首先要确保 apport 在运行。可以通过 systemctl status apport 查看。也可以看下 apport 日志:

触发一次 core dump,会看到:

意思是 core dump 不是来自于 ubuntu 打包的软件,忽略。

配置方法是,修改 ~/.config/apport/settings (如果没有,手动创建)文件,写入:

再触发一次 core dump,这次日志里就会有写入的信息了:

还要注意的是,这个文件不是 core dump 文件,而是 apport 打包的 debug 文件,可以使用 apport-unpack 解包:

解包出来的 CoreDump 就可以用 gdb 分析了。其他的文件记录了一些系统相关的信息。(感觉是 Ubuntu 用来让用户报告 bug 的)

 

最后,如果进程的 workdir 下没有生成 core dump 的话,可以看下是不是在 /var/lib/systemd/coredump/,网上说用 systemd 的系统会存放在这里,不过我没遇到。



Leave a comment

您的电子邮箱地址不会被公开。 必填项已用 * 标注