2014-04-29 35 views
7

Go進程正在運行。我想如何轉儲所有Go進程的堆棧?

  1. 轉儲它的每一個夠程
  2. 來自外部的堆棧跟蹤,不依賴於任何我添加到它的源代碼
  3. 沒有殺死它。

我該怎麼做?

這應該很容易 - 功能被要求:https://code.google.com/p/go/issues/detail?id=2516,並根據該線程的結論,實施。那是兩年前的事了。但是,問題線程和提交都不包含有關如何調用此功能的任何提示。

功能請求提到SIGQUIT調用JVM上的相應功能,但事實並非如此;至少在go1.2上,SIGQUIT會執行#1和#2,但也會殺死進程。

前一個人有人問這個問題:How to dump goroutine stacktraces? 但他們沒有明確要求#2或#3,沒有答案滿足#2,他們接受了一個不符合#2的答案。所以這是一個不同的問題。

+2

看起來你必須在程序中添加一些東西來捕獲SIGQUIT並在鏈接的答案中運行代碼。我沒有看到Brad的更改列表中的任何內容,表明它添加了默認的信號處理程序或類似的東西。 – twotwotwo

回答

3

如果您使用的是net/http,您可以通過調試處理程序訪問goroutines。如果你看一下下面的源

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

您將看到輪廓,goroutineProfile,上線62此配置文件通過writeGoroutine寫出。如果使用調試> = 2調用writeGoroutine,則會寫出所有的goroutine。

您應該可以通過curl http://localhost:<port>/debug/pprof/goroutine?debug=2來獲得所有的goroutines傾倒。不幸的是,我沒有看到任何可以調用該代碼的信號處理程序的引用,但是您可以查看pprof如何在源代碼中使用runtime.Stack的引用來輕鬆實現這一點。

9

您可以設置一個處理程序一樣,使用代碼是這樣的:

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) 


    ... 
} 

SIGQUIT信號現在將抓住送到指定的頻道。然後使用runtime.Stack函數將堆棧跟蹤格式化爲準備好的緩衝區(如果它大於緩衝區,它將被截斷),然後打印。

+0

不符合要求#2 – Bryan