dsnpjz6907 2016-01-13 16:32
浏览 415
已采纳

在golang中捕获panic()

We have a large-ish golang application that uses the logger (actually, a custom logger), to write output to a log file that is periodically rotated.

However, when an application crashes or panic()'s, those messages go to standard error.

Is there any way to override the panic functionality to use our logger?

  • 写回答

3条回答 默认 最新

  • dongxiaoshe0737 2016-01-13 18:06
    关注

    As far as I know, you can't redirect the output from panic away from standard error, or to your logger. The best thing you can do is redirect standard error to a file which you can do externally, or inside your program.

    For my rclone program I redirected standard error to capture everything to a file on an option which is unfortunately isn't particularly easy to do in a cross platform way. Here is how I did it (see the redirect*.go files)

    For linux/unix

    // 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)
        }
    }
    

    and for 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
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥30 Matlab打开默认名称带有/的光谱数据
  • ¥50 easyExcel模板 动态单元格合并列
  • ¥15 res.rows如何取值使用
  • ¥15 在odoo17开发环境中,怎么实现库存管理系统,或独立模块设计与AGV小车对接?开发方面应如何设计和开发?请详细解释MES或WMS在与AGV小车对接时需完成的设计和开发
  • ¥15 CSP算法实现EEG特征提取,哪一步错了?
  • ¥15 游戏盾如何溯源服务器真实ip?需要30个字。后面的字是凑数的
  • ¥15 vue3前端取消收藏的不会引用collectId
  • ¥15 delphi7 HMAC_SHA256方式加密
  • ¥15 关于#qt#的问题:我想实现qcustomplot完成坐标轴
  • ¥15 下列c语言代码为何输出了多余的空格