如何转储所有Go进程的堆栈?

Gre*_*ice 10 go

Go进程正在运行.我想要

  1. 转储每个goroutine的堆栈跟踪
  2. 从外部,不依赖于我添加到其源代码中的任何内容
  3. 没有杀死它.

我怎样才能做到这一点?

这应该很简单 - 请求功能:https://code.google.com/p/go/issues/detail?id = 2516,并根据该主题的结论,实施.那是两年多以前的事了.但是问题线程和提交都没有包含关于如何调用此功能的任何提示.

功能请求提到SIGQUIT调用JVM上的相应功能,但事实并非如此; 至少在go1.2上,SIGQUIT做#1和#2但也杀死了这个过程.

有人在前面问了一个相关的问题:如何转储goroutine stacktraces? 但他们没有明确要求#2或#3,没有一个答案符合#2,他们接受了不符合#2的答案.所以这是一个不同的问题.

Jam*_*dge 10

您可以使用以下代码设置这样的处理程序:

import (
    "fmt"
    "os"
    "os/signal"
    "runtime"
    "syscall"
)

func main() {
    sigChan := make(chan os.Signal)
    go func() {
        stacktrace := make([]byte, 8192)
        for _ = range sigChan {
            length := runtime.Stack(stacktrace, true)
            fmt.Println(string(stacktrace[:length]))
        }
    }()
    signal.Notify(sigChan, syscall.SIGQUIT)


    ...
}
Run Code Online (Sandbox Code Playgroud)

SIGQUIT信号现在将抓住送到指定的频道.runtime.Stack然后使用该函数将堆栈跟踪格式化为准备好的缓冲区(如果它大于缓冲区,它将被截断),然后打印.


小智 6

如果您使用 net/http,您可以通过调试处理程序访问 goroutine。如果您查看以下来源

http://golang.org/src/pkg/runtime/pprof/pprof.go

您将goroutineProfile在第 62 行看到配置文件。该配置文件通过 写出writeGoroutine。如果 writeGoroutine 在 debug >= 2 的情况下被调用,那么它将写出所有的 goroutine。

您应该能够将curl http://localhost:<port>/debug/pprof/goroutine?debug=2所有 goroutine 转储。不幸的是,我没有看到任何对调用该代码的信号处理程序的引用,但您可以查看 pprof 如何runtime.Stack在上面的源代码中使用的引用来自己轻松实现这一点。