Tôi có nền tảng Java và tôi thích sử dụng signal QUIT để kiểm tra kết xuất chuỗi Java.
Làm thế nào để Golang in ra tất cả dấu vết ngăn xếp goroutines?
Tôi có nền tảng Java và tôi thích sử dụng signal QUIT để kiểm tra kết xuất chuỗi Java.
Làm thế nào để Golang in ra tất cả dấu vết ngăn xếp goroutines?
Câu trả lời:
Để in dấu vết ngăn xếp cho quy trình hiện tại , hãy sử dụng PrintStack()
từruntime/debug
.
PrintStack in ra lỗi tiêu chuẩn dấu vết ngăn xếp do Stack trả về.
Ví dụ:
import(
"runtime/debug"
)
...
debug.PrintStack()
Để in dấu vết ngăn xếp cho tất cả các goroutines sử dụng Lookup
và WriteTo
từ runtime/pprof
.
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.
Mỗi Hồ sơ có một tên duy nhất. Một số cấu hình được xác định trước:
goroutine - dấu vết ngăn xếp của tất cả
đống goroutines hiện tại - lấy mẫu tất cả phân bổ heap
luồng tạo - dấu vết ngăn xếp dẫn đến việc tạo
khối luồng hệ điều hành mới - dấu vết ngăn xếp dẫn đến việc chặn trên nguyên thủy đồng bộ hóa
Ví dụ:
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
Stack
. "Stack trả về một dấu vết ngăn xếp được định dạng của quy trình gọi nó. Đối với mỗi quy trình, nó bao gồm thông tin dòng nguồn và giá trị PC, sau đó cố gắng khám phá, đối với các hàm Go, hàm hoặc phương thức gọi và văn bản của dòng chứa lời kêu gọi. "
Có một giao diện người dùng HTTP cho runtime/pprof
gói được đề cập trong câu trả lời của Intermernet. Nhập gói net / http / pprof để đăng ký một trình xử lý HTTP cho /debug/pprof
:
import _ "net/http/pprof"
import _ "net/http"
Bắt đầu trình nghe HTTP nếu bạn chưa có:
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
Sau đó, trỏ trình duyệt đến http://localhost:6060/debug/pprof
một menu hoặc http://localhost:6060/debug/pprof/goroutine?debug=2
cho một kết xuất ngăn xếp quy trình đầy đủ.
Có những điều thú vị khác mà bạn có thể tìm hiểu về mã đang chạy của mình theo cách này. Xem bài đăng trên blog để biết ví dụ và biết thêm chi tiết: http://blog.golang.org/profiling-go-programs
Để bắt chước hành vi Java của stack-dump trên SIGQUIT nhưng vẫn để chương trình chạy:
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])
}
}()
Tương tự như Java, SIGQUIT có thể được sử dụng để in dấu vết ngăn xếp của một chương trình Go và các goroutines của nó.
Tuy nhiên, một điểm khác biệt chính là theo mặc định, việc gửi SIGQUIT tới các chương trình Java không chấm dứt chúng, trong khi các chương trình Go thoát.
Cách tiếp cận này không yêu cầu thay đổi mã để in dấu vết ngăn xếp của tất cả các goroutines của các chương trình hiện có.
Biến môi trường GOTRACEBACK ( xem tài liệu của gói thời gian chạy ) kiểm soát số lượng đầu ra được tạo. Ví dụ: để bao gồm tất cả các goroutines, hãy đặt GOTRACEBACK = all.
Việc in dấu vết ngăn xếp được kích hoạt bởi một điều kiện thời gian chạy không mong muốn (tín hiệu không được xử lý), ban đầu được ghi lại trong cam kết này , làm cho nó có sẵn kể từ ít nhất Go 1.1.
Ngoài ra, nếu sửa đổi mã nguồn là một tùy chọn, hãy xem các câu trả lời khác.
Lưu ý rằng trong một thiết bị đầu cuối Linux, SIGQUIT có thể được gửi một cách thuận tiện bằng tổ hợp phím Ctrl+ \.
Bạn có thể sử dụng runtime.Stack để lấy dấu vết ngăn xếp của tất cả các goroutines:
buf := make([]byte, 1<<16)
runtime.Stack(buf, true)
fmt.Printf("%s", buf)
Từ tài liệu:
func Stack(buf []byte, all bool) int
Stack định dạng một dấu vết ngăn xếp của goroutine đang gọi thành buf và trả về số byte được ghi vào buf. Nếu tất cả đều đúng, các định dạng Stack sẽ xếp dấu vết của tất cả các goroutines khác vào buf sau dấu vết cho goroutine hiện tại.
string(buf)
ở đây, fmt.Printf("%s", buf)
và fmt.Printf("%s", string(buf))
làm điều tương tự (xem tài liệu về fmt
gói); sự khác biệt duy nhất ở đây là string
phiên bản sẽ sao chép các byte từ buf
không cần thiết
Nhấn CTRL + \
(Nếu bạn chạy nó trong một thiết bị đầu cuối và chỉ muốn giết chương trình của mình và kết xuất các quy trình hoạt động, v.v.)
Tôi tìm thấy câu hỏi này đang tìm kiếm chuỗi khóa. Tôi chỉ muốn một cách nhanh chóng và dễ dàng để biết liệu chương trình của tôi có bị rò rỉ quy trình hoạt động hay không :)
Trên hệ thống * NIX (bao gồm OSX) gửi tín hiệu hủy bỏ SIGABRT
:
pkill -SIGABRT program_name
Cần sử dụng độ dài được trả về runtime.Stack()
để tránh in một loạt các dòng trống sau dấu vết ngăn xếp của bạn. Hàm khôi phục sau sẽ in ra một dấu vết được định dạng độc đáo:
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]))
}
Theo mặc định, nhấn ^\
các phím ( CTRL + \ ) để kết xuất dấu vết ngăn xếp của tất cả các goroutines.
Nếu không, để kiểm soát chi tiết hơn, bạn có thể sử dụng panic
. Cách đơn giản kể từ Go 1.6+ :
go func() {
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGQUIT)
<-s
panic("give me the stack")
}()
Sau đó, chạy chương trình của bạn như sau:
# Press ^\ to dump the stack traces of all the user-created goroutines
$ GOTRACEBACK=all go run main.go
Nếu bạn cũng muốn in goroutines thời gian chạy:
$ GOTRACEBACK=system go run main.go
Đây là tất cả các tùy chọn GOTRACEBACK:
GOTRACEBACK=none
bỏ qua hoàn toàn dấu vết ngăn xếp goroutine.GOTRACEBACK=single
(mặc định) hoạt động như mô tả ở trên.GOTRACEBACK=all
thêm dấu vết ngăn xếp cho tất cả các goroutines do người dùng tạo.GOTRACEBACK=system
giống như `` tất cả '' nhưng thêm khung ngăn xếp cho các chức năng thời gian chạy và hiển thị các goroutines được tạo nội bộ bởi thời gian chạy.GOTRACEBACK=crash
giống như `` hệ thống '' nhưng bị treo theo cách dành riêng cho hệ điều hành thay vì thoát ra. Ví dụ, trên các hệ thống Unix, sự cố xảy ra SIGABRT
để kích hoạt kết xuất lõi.Biến GOTRACEBACK kiểm soát lượng đầu ra được tạo ra khi chương trình Go bị lỗi do sự cố không được khắc phục hoặc điều kiện thời gian chạy không mong muốn.
Theo mặc định, lỗi sẽ in dấu vết ngăn xếp cho quy trình hiện tại, làm sáng tỏ các chức năng bên trong hệ thống thời gian chạy và sau đó thoát với mã thoát 2. Lỗi in dấu vết ngăn xếp cho tất cả các quy trình nếu không có quy trình hiện tại hoặc lỗi là bên trong thời gian chạy.
Vì lý do lịch sử, cài đặt GOTRACEBACK 0, 1 và 2 là từ đồng nghĩa với không, tất cả và hệ thống, tương ứng.
Hàm SetTraceback của gói thời gian chạy / gỡ lỗi cho phép tăng số lượng đầu ra tại thời gian chạy, nhưng nó không thể giảm số lượng dưới mức được chỉ định bởi biến môi trường. Xem https://golang.org/pkg/runtime/debug/#SetTraceback .