Go プログラムをサーバーとして実行しているため、後で分析およびデバッグするために問題が発生した場合にパニック ログをキャッチするメカニズムが必要です。UnixでGoプログラムのパニックログを簡単に取得する効率的な方法はありますか? これについてのあなたの経験を紹介できますか?ありがとう :)
2 に答える
外出先のプログラムで致命的なパニックが発生したという通知が電話に届きます。方法は次のとおりです。
まず、私は通常、daemontools (または同様のもの) の下ですべてを実行するので、監視され、障害が発生した場合は自動的に再起動します。
次に、通常、組み込みのログ パッケージを使用して syslog にログを記録します。私の syslog はpapertrailに転送され、そこで状態を確認したり、アラートを設定したりできます... ここで、望ましくないイベントの通知をメール アドレスに転送し、 myandroidに通知することで、問題を認識したり、同様の最近の問題を検索したりできます、問題の前後関係を調べるなど...
...しかし、キャッチされていない独自の致命的なパニックをログに記録することはできないため、logexecを作成して、プログラムを実行し、失敗した終了通知と共にその stdout と stderr を個別にログに記録しました。
例:
logexec -tag myprogram /path/to/myprogram -and -its arguments
プログラムでいくつかの問題をキャッチし、それらのパニック ログを処理することが可能です。しかし、それはうまくいきません。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 を任意の場所 (パイプ、ファイルなど) にリダイレクトします。