如何转储goroutine stacktraces?

我有Java背景,我喜欢用QUIT来检查Java线程转储。

如何让Golang打印出所有的goroutines堆栈跟踪?

要打印当前 goroutine的堆栈跟踪,请使用runtime/debug PrintStack()

PrintStack打印标准错误堆栈返回的堆栈跟踪。

例如:

 import( "runtime/debug" ) ... debug.PrintStack() 

要打印所有 runtime/pprof的堆栈跟踪,请使用runtime/pprof LookupWriteTo

 func Lookup(name string) *Profile // Lookup returns the profile with the given name, // or nil if no such profile exists. func (p *Profile) WriteTo(w io.Writer, debug int) error // WriteTo writes a pprof-formatted snapshot of the profile to w. // If a write to w returns an error, WriteTo returns that error. // Otherwise, WriteTo returns nil. 

每个configuration文件都有唯一的名称。 一些configuration文件是预定义的:

goroutine – 所有当前goroutines的堆栈痕迹
堆 – 所有堆分配的抽样
threadcreate – 导致创build新操作系统线程的堆栈跟踪
导致阻塞同步原语的块堆栈跟踪

例如:

 pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) 

在Intermernet的答案中提到了runtime/pprof包的HTTP前端。 导入net / http / pprof包来为/debug/pprof注册一个HTTP处理程序:

 import _ "net/http/pprof" import _ "net/http" 

如果您还没有HTTP侦听器,请启动它:

 go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }() 

然后将浏览器指向http://localhost:6060/debug/pprof作为菜单,或者对于完整的goroutine堆栈转储,使用http://localhost:9100/debug/pprof/goroutine?debug=2

更多细节在这里: http : //blog.golang.org/profiling-go-programs

为了模拟SIGQUIT上堆栈转储的Java行为,但仍然运行程序:

 go func() { sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGQUIT) buf := make([]byte, 1<<20) for { <-sigs stacklen := runtime.Stack(buf, true) log.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf[:stacklen]) } }() 

你可以使用runtime.Stack获取所有协程的堆栈跟踪:

 buf := make([]byte, 1<<16) runtime.Stack(buf, true) fmt.Printf("%s", buf) 

从文档:

 func Stack(buf []byte, all bool) int 

堆栈将调用的goroutine的堆栈跟踪格式化为buf,并返回写入buf的字节数。 如果全部为真,则堆栈格式将当前goroutine的跟踪之后的所有其他goroutines的跟踪堆栈跟踪到buf中。

根据运行时软件包的文档 ,发送一个SIGQUIT到一个Go程序默认情况下会为每个现存的goroutine打印一个堆栈跟踪,在运行系统内部隐藏函数,然后退出,退出代码为2。

环境variablesGOTRACEBACK控制生成的输出量。 要包含所有的goroutine,不要过滤,设置GOTRACEBACK = 2。 要额外生成核心转储(在Unix系统上),请设置GOTRACEBACK = crash。

在这个提交中添加了文档和生成核心转储的能力,自从1.1版以来,AFAICT就可以使用了。

所以这种方法不需要代码来打印所有goroutines的堆栈跟踪。 与Java的区别在于Java将继续运行程序,而Go将退出。

在* NIX系统(包括OSX)发送信号中止SIGABRT

pkill -SIGABRT program_name

有必要使用由runtime.Stack()返回的长度来避免在堆栈跟踪之后打印大量空行。 以下恢复function打印格式良好的跟踪:

 if r := recover(); r != nil { log.Printf("Internal error: %v", r)) buf := make([]byte, 1<<16) stackSize := runtime.Stack(buf, true) log.Printf("%s\n", string(buf[0:stackSize])) } 

按下CTRL + \

(如果你在terminal上运行它,只想杀死你的程序并转储掉程序等等)

我发现这个问题寻找关键序列。 只是想要一个快速简单的方法来告诉我的程序是否泄漏去例程:)