如何转储goroutine stacktraces?
我有Java背景,我喜欢用QUIT来检查Java线程转储。
如何让Golang打印出所有的goroutines堆栈跟踪?
要打印当前 goroutine的堆栈跟踪,请使用runtime/debug
PrintStack()
。
PrintStack打印标准错误堆栈返回的堆栈跟踪。
例如:
import( "runtime/debug" ) ... debug.PrintStack()
要打印所有 runtime/pprof
的堆栈跟踪,请使用runtime/pprof
Lookup
和WriteTo
。
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上运行它,只想杀死你的程序并转储掉程序等等)
我发现这个问题寻找关键序列。 只是想要一个快速简单的方法来告诉我的程序是否泄漏去例程:)