由于我将 Go 程序作为服务器运行,因此如果出现任何问题,我需要一些机制来捕获恐慌日志以供以后分析和调试。有没有什么有效的方法可以轻松获取 Unix 下 Go 程序的恐慌日志?各位能不能介绍一下这方面的经验?谢谢 :)
问问题
399 次
2 回答
7
我在手机上收到一条通知,说明我对 Go 程序的一些致命恐慌。就是这样:
首先,我通常在daemontools(或类似工具)下运行所有内容,以便对其进行监控并在失败时自行重启。
然后,我一般使用内置的日志包登录到 syslog。我的 syslog 转发到papertrail,在那里我可以查看事物的状态、设置警报等...在这里我将不需要的事件通知转发到电子邮件地址并notifymyandroid以便我可以了解问题,搜索类似的近期问题,查看问题的上下文等...
...但是您无法记录自己未捕获的致命恐慌,因此我编写了logexec来执行程序并分别记录其 stdout 和 stderr 以及不成功的退出通知。
例子:
logexec -tag myprogram /path/to/myprogram -and -its arguments
于 2013-05-09T16:01:37.370 回答
3
可以以编程方式捕获一些问题并为它们处理恐慌日志。但它不适用于例如。OOM 错误或死锁。
有限的情况可以这样说明,例如:
package main
import (
"fmt"
"os"
"runtime"
)
func fact(n int) int {
if 1/n == 42 {
return 314
}
return n * fact(n-1)
}
func main() {
const maxTrace = 1000
defer func() {
if e := recover(); e != nil {
fmt.Fprintf(os.Stderr, "Panic log, recovered: '%v'", e)
var b [maxTrace]byte
fmt.Fprintf(os.Stderr, "%s", b[:runtime.Stack(b[:], true)])
}
}()
fact(3)
}
输出:
Panic log, recovered: 'runtime error: integer divide by zero'goroutine 1 [running]:
main.func·001()
/tmpfs/gosandbox-9ec179e4_f9a94b22_357f29a2_2f5f25c4_b484febf/prog.go:23 +0x14b
main.fact(0x0, 0x4103f1)
/tmpfs/gosandbox-9ec179e4_f9a94b22_357f29a2_2f5f25c4_b484febf/prog.go:10 +0x2b
main.fact(0x1, 0x0)
/tmpfs/gosandbox-9ec179e4_f9a94b22_357f29a2_2f5f25c4_b484febf/prog.go:14 +0x54
main.fact(0x2, 0x0)
/tmpfs/gosandbox-9ec179e4_f9a94b22_357f29a2_2f5f25c4_b484febf/prog.go:14 +0x54
main.fact(0x3, 0x401005)
/tmpfs/gosandbox-9ec179e4_f9a94b22_357f29a2_2f5f25c4_b484febf/prog.go:14 +0x54
main.main()
/tmpfs/gosandbox-9ec179e4_f9a94b22_357f29a2_2f5f25c4_b484febf/prog.go:27 +0x37
要在任何类型的进程崩溃(包括 OOM 和死锁)上捕获所有goroutine的堆栈跟踪,...:将其 stderr 重定向到任何所需的位置(例如管道、文件)。
于 2013-05-09T12:49:27.877 回答