获取 recover 的 Panic 信息
适用于 recover 之后查看具体的调用栈
func panicTrace(kb int) []byte {
s := []byte("/src/runtime/panic.go")
e := []byte("\ngoroutine ")
line := []byte("\n")
stack := make([]byte, kb<<10) //4KB
length := runtime.Stack(stack, true)
start := bytes.Index(stack, s)
stack = stack[start:length]
start = bytes.Index(stack, line) + 1
stack = stack[start:]
end := bytes.LastIndex(stack, line)
if end != -1 {
stack = stack[:end]
}
end = bytes.Index(stack, e)
if end != -1 {
stack = stack[:end]
}
stack = bytes.TrimRight(stack, "\n")
return stack
}
将 Panic 错误保存在文件中
适用于不知道何时会 panic 的情况,应该写在程序开头
// RewriteStderrFile 将标准错误保存到stderr中
func RewriteStderrFile() error {
if runtime.GOOS == "windows" {
return nil
}
stdErrFile := fmt.Sprintf("%s/stderr.log", LogPath)
file, err := os.OpenFile(stdErrFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return err
}
stdErrFileHandler = file
if err = syscall.Dup2(int(file.Fd()), int(os.Stderr.Fd())); err != nil {
return err
}
// 内存回收前关闭文件描述符
runtime.SetFinalizer(stdErrFileHandler, func(fd *os.File) {
fd.Close()
})
return nil
}