標準愚痴出力

個人的なIT作業ログです。もしかしたら一般的に参考になることが書いているかもしれません(弱気

もう一つの《Go で「予期せぬエラー」(panic)をファイルに記録する方法》

この方法だと、panic が起らない場合もゼロバイトのファイルが作成されてしまう。

panic が起きてから、"runtime/debug".Stack() で、スタックトレースを得るという方法もある。 この方法は Go 1.20 でも使えるというメリットもある。

nyagos で使用している関数を抜粋する。

import (
    "bytes"
    "fmt"
    "io"
    "os"
    "runtime/debug"
)

func main() {
    defer PanicHandler()
        // 以下略
}


func PanicHandler() {
    err := recover()
    if err == nil {
        return
    }
    var dump bytes.Buffer
    w := io.MultiWriter(os.Stderr, &dump)

    fmt.Fprintln(w, "************ Panic Occurred. ***********")
    fmt.Fprintln(w, "** err **")
    fmt.Fprintln(w, err)
    fmt.Fprintln(w, "** debug.Stack **")
    w.Write(debug.Stack())
    fmt.Fprintln(w, "*** Please copy these error message ***")
    fmt.Fprintln(w, "*** And hit ENTER key to quit.      ***")

    os.WriteFile("nyagos.dump", dump.Bytes(), 0666)

    var dummy [1]byte
    os.Stdin.Read(dummy[:])
}

わざと panic を起こすと次のような内容のファイル: nyagos.dump が作成される

************ Panic Occurred. ***********
** err **
panic test
** debug.Stack **
goroutine 1 [running]:
runtime/debug.Stack()
    C:/Users/hymko/sdk/go1.20.14/src/runtime/debug/stack.go:24 +0x65
github.com/nyaosorg/nyagos/internal/frame.PanicHandler()
    C:/Users/hymko/src/nyagos/internal/frame/main.go:67 +0x3ef
panic({0x7bcce0, 0x8a0f30})
    C:/Users/hymko/sdk/go1.20.14/src/runtime/panic.go:884 +0x213
github.com/nyaosorg/nyagos/internal/commands.cmdPanic({0xc002506390, 0xc002506a00}, {0xc0002f6390, 0x2})
    C:/Users/hymko/src/nyagos/internal/commands/table_windows.go:77 +0x27
github.com/nyaosorg/nyagos/internal/commands.Exec({0x8a3cb8, 0xc00017b0e0}, {0x8a5fa0, 0xc0003240f0})
    C:/Users/hymko/src/nyagos/internal/commands/commands.go:71 +0x18c
github.com/nyaosorg/nyagos/internal/frame.Setup.func1({0x8a3cb8?, 0xc00017b0e0?}, 0xc0002f6390?)
    C:/Users/hymko/src/nyagos/internal/frame/main.go:33 +0x2d
github.com/nyaosorg/nyagos/internal/alias.hook({0x8a3cb8, 0xc00017b0e0}, 0xc0003240f0)
    C:/Users/hymko/src/nyagos/internal/alias/alias.go:58 +0x16b
github.com/nyaosorg/nyagos/internal/shell.New.func1({0x8a3cb8?, 0xc00017b0e0?}, 0x674ee0?)
    C:/Users/hymko/src/nyagos/internal/shell/interpreter.go:206 +0x2f
github.com/nyaosorg/nyagos/internal/shell.(*Cmd).spawnvpSilent(0xc0003240f0, {0x8a3cb8, 0xc00017b0e0})
    C:/Users/hymko/src/nyagos/internal/shell/interpreter.go:340 +0x2d8
github.com/nyaosorg/nyagos/internal/shell.(*Cmd).Spawnvp(0xc0003240f0, {0x8a3c10, 0xc00031e280})
    C:/Users/hymko/src/nyagos/internal/shell/interpreter.go:443 +0xec
github.com/nyaosorg/nyagos/internal/shell.(*Shell).Interpret(0xc000027e00, {0x8a3c10, 0xc00031e280}, {0xc0002f6350?, 0xc000075be8?})
    C:/Users/hymko/src/nyagos/internal/shell/interpreter.go:595 +0xabe
github.com/nyaosorg/nyagos/internal/shell.(*Shell).Loop(0xc000027e00, {0x8a3cb8, 0xc00038e780}, {0x8a2d10?, 0xc000008960?})
    C:/Users/hymko/src/nyagos/internal/shell/loop.go:131 +0x2ae
github.com/nyaosorg/nyagos/internal/shell.(*Shell).ForEver(...)
    C:/Users/hymko/src/nyagos/internal/shell/loop.go:157
github.com/nyaosorg/nyagos/internal/mains.Run({0x8a1d20, 0xad4308})
    C:/Users/hymko/src/nyagos/internal/mains/nyagos.go:209 +0xb7b
main.run()
    C:/Users/hymko/src/nyagos/main.go:27 +0x71
main.main()
    C:/Users/hymko/src/nyagos/main.go:31 +0x1d
*** Please copy these error message ***
*** And hit ENTER key to quit.      ***