這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。程式調試對於檢查和理解程式運行過程和狀態是非常有用的。一個核心轉儲檔案( core dump file )中包含程式進程運行時的記憶體資訊和進程狀態。它主要用於程式的問題調試,以及在運行過程中理解程式的狀態。這些對於我們診斷程式問題原因和分析生產環境中的服務問題有非常大的協助。在本文中,我會用一個非常簡單的 hello world 網頁應用服務舉例,實際情況,我們的程式會更加複雜。對核心轉儲檔案的分析意義在於可以協助我們查看程式當時的運行情況,並可能讓我們有機會重現當時的程式問題。**注意**: 接下來的操作都是在Linux系統終端中執行,我不確定其它類Unix系統是否可以工作正常,macOS 和 Windows 應該都不支援。在開始之前,你需要確定已經開啟了作業系統對核心轉儲檔案的支援。 `ulimit` 的預設值為 0 意思是說核心轉儲檔案最大容量只能是零。我通常在開發機上設定為 `unlimited` 命令如下: $ ulimit -c unlimited然後,確定你的機器上已經安裝了 [delve](https://github.com/derekparker/delve) 。這是一個 `main.go` 檔案,包含一個HTTP啟動服務和一個處理函數。``` go$ cat main.gopackage mainimport ( "fmt" "log" "net/http")func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "hello world\n") }) log.Fatal(http.ListenAndServe("localhost:7777", nil))}```我們把它編譯成二進位檔案。 $ go build .我們假設下,將來這個服務可能會出現問題,但是你不知道會出現什麼樣的問題。你可能已經用了很多方法測試程式但仍然找不到程式異常退出的原因。一般在這種情況下,最好能夠有當時程式進程的快照,然後用你的調試工具對快照進行調試。有很多種方式可以獲得程式的核心轉儲檔案。你可能已經熟悉程式崩潰轉儲方式,當程式崩潰時會將崩潰時的程式核心資訊寫入磁碟檔案。Go 預設是不開啟程式崩潰轉儲的,但是你可以設定 `GOTRACEBACK` 為 `crash` 來開啟 Ctrl + backslash 產生崩潰轉儲檔案。 $ GOTRACEBACK=crash ./hello (Ctrl+\)這樣就可以使程式崩潰並將堆疊追蹤列印寫入核心轉儲檔案。另一種方法是從正在啟動並執行進程中產生核心轉儲檔案,而不必殺死進程。使用 `gcore` 選項就可以在不崩潰的情況下產生核心轉儲檔案。我們重新啟動程式: $ ./hello & $ gcore 546 # 546 is the PID of hello.我們已經可以在程式不崩潰的情況下拿到核心轉儲檔案。下一步通過 delve 載入核心轉儲檔案進行分析。 $ dlv core ./hello core.546這和 delve 的一般用法是相同的。你可以回放,查看代碼,查看變數等。有些功能會被禁用,畢竟核心轉儲檔案只是快照,而不是真實的進程情況,但程式的執行過程和進程狀態是完全可以訪問的。 (dlv) bt 0 0x0000000000457774 in runtime.raise at /usr/lib/go/src/runtime/sys_linux_amd64.s:110 1 0x000000000043f7fb in runtime.dieFromSignal at /usr/lib/go/src/runtime/signal_unix.go:323 2 0x000000000043f9a1 in runtime.crash at /usr/lib/go/src/runtime/signal_unix.go:409 3 0x000000000043e982 in runtime.sighandler at /usr/lib/go/src/runtime/signal_sighandler.go:129 4 0x000000000043f2d1 in runtime.sigtrampgo at /usr/lib/go/src/runtime/signal_unix.go:257 5 0x00000000004579d3 in runtime.sigtramp at /usr/lib/go/src/runtime/sys_linux_amd64.s:262 6 0x00007ff68afec330 in (nil) at :0 7 0x000000000040f2d6 in runtime.notetsleep at /usr/lib/go/src/runtime/lock_futex.go:209 8 0x0000000000435be5 in runtime.sysmon at /usr/lib/go/src/runtime/proc.go:3866 9 0x000000000042ee2e in runtime.mstart1 at /usr/lib/go/src/runtime/proc.go:1182 10 0x000000000042ed04 in runtime.mstart at /usr/lib/go/src/runtime/proc.go:1152 (dlv) ls > runtime.raise() /usr/lib/go/src/runtime/sys_linux_amd64.s:110 (PC: 0x457774) 105:SYSCALL 106:MOVLAX, DI// arg 1 tid 107:MOVLsig+0(FP), SI// arg 2 108:MOVL$200, AX// syscall - tkill 109:SYSCALL => 110:RET 111: 112:TEXT runtime·raiseproc(SB),NOSPLIT,$0 113:MOVL$39, AX// syscall - getpid 114:SYSCALL 115:MOVLAX, DI// arg 1 pid
via: https://rakyll.org/coredumps/
作者:rakyll 譯者:jzhongming 校對:Unknwon
本文由 GCTT 原創編譯,Go語言中文網 榮譽推出
本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽
1073 次點擊 ∙ 2 贊