// Log the panic under unix to the log file
//+build unix
package main
import (
"log"
"os"
"syscall"
)
// redirectStderr to the file passed in
func redirectStderr(f *os.File) {
err := syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd()))
if err != nil {
log.Fatalf("Failed to redirect stderr to file: %v", err)
}
}
和windows
// Log the panic under windows to the log file
//
// Code from minix, via
//
// http://play.golang.org/p/kLtct7lSUg
//+build windows
package main
import (
"log"
"os"
"syscall"
)
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
)
func setStdHandle(stdhandle int32, handle syscall.Handle) error {
r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
if r0 == 0 {
if e1 != 0 {
return error(e1)
}
return syscall.EINVAL
}
return nil
}
// redirectStderr to the file passed in
func redirectStderr(f *os.File) {
err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
if err != nil {
log.Fatalf("Failed to redirect stderr to file: %v", err)
}
// SetStdHandle does not affect prior references to stderr
os.Stderr = f
}
defer func() {
if x := recover(); x != nil {
// recovering from a panic; x contains whatever was passed to panic()
log.Printf("run time panic: %v", x)
// if you just want to log the panic, panic again
panic(x)
}
}()
panic("foo");
4条答案
按热度按时间fwzugrvs1#
据我所知,你不能将panic的输出重定向到标准错误,也不能重定向到你的logger。你能做的最好的事情就是将标准错误重定向到一个文件中,你可以在外部或程序内部这样做。
对于我的rclone程序,我重定向了标准错误,以捕获所有内容到一个选项上的文件中,不幸的是,这在跨平台的方式中并不是特别容易做到。下面是我如何做到这一点(见重定向 *.go文件)
对于Linux/unix
和windows
sc4hvdpw2#
你可以使用
recover()
从同一个goroutine中恢复panics。当在延迟方法中调用recover()
时(记住延迟方法仍然会被调用,即使在panic()
ing时),它将返回作为参数传递到最后一次panic()
调用的任何内容(或者当程序没有恐慌时返回nil
)。但是请注意,您无法从不同goroutine中触发的panic中恢复(感谢JimB的提示)。使用单个
recover()
从任何goroutine的恐慌中恢复是不可能的。3pvhb19x3#
扩展@nick-craig-wood的回答:如果你在Linux上,你可以生成一个logger(1)示例并将stderr重定向到它。这样,您就可以将完整的回溯跟踪到syslog中。下面是gocryptfs所做的:
lyfkaqu14#
更新到2023年。
syscall.SysCall
已被弃用,所以我正在寻找一种在Windows上捕获恐慌的替代方法。安德鲁·麦金利的回答对我很有效。下面是我用来捕获恐慌并发送到日志文件的代码pidoss. Rclone是一个令人敬畏的工具!