最近、Golang で書かれたプログラムで非常に奇妙な問題に遭遇しました。つまり、プロセスが自動的に消えてしまいます。いくつかのトラブルシューティングを行った後、問題を見つけたので、いくつかの経験をまとめました。以下に私が遭遇した問題と解決策を共有しましょう。
当社の製品は毎日定期的にタスクを実行していますが、ここ数日、タスクが常に数分後に停止することがわかり、プロセスのログ出力を設定しました。をファイルに書き込み、ログを確認したところ、プロセスは数分間だけ実行され、その後自然に消えたことがわかりました。通常の開発やテストでは同様の問題に遭遇したことがないため、この状況は非常に奇妙です。
まず、最も簡単な解決策を考えました。それは、コードにデバッグ情報を追加することでした。そこで、プロセスを開始したときに start
のログを出力し、その後、重要な操作を実行するたびに、対応するログを出力しました。そこでタスクを再起動し、停止するのを待ってログを確認したところ、プロセスは開始から数分で停止しましたが、ログにはエラーメッセージは出力されず、終了したようでした。自体。
次に、strace
コマンドを使用してプロセスのシステム コールをトレースし、プロセスが終了した理由を確認してみました。ただし、このプロセスの構造は比較的複雑で、複数のゴルーチンが実行されます。 strace
コマンドを使用してゴルーチンの 1 つ (ndeliver) をトレースし、そのシステム コールを確認しました。 ndeliver
goroutine の関連コードは次のとおりです。
c := make(chan os.Signal, 1) signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) go func() { sig := <-c log.Errorf("main: received signal %s, shutting down server", sig.String()) server.Stop() os.Exit(0) }() go func() { err := server.Start() if err != nil { log.Fatalf("ndeliver: server start error: %s", err) } }()
このコードの機能は、プロセスの信号処理関数を登録し、ゴルーチンを開始して server.Start を実行することです。 ()
関数。この関数はプロセスが終了するまでブロックされます。
strace
コマンドにより、このゴルーチンには例外がなく、エラーが発生することなく終了したことがわかりました。しかし、プロセス中に他のゴルーチンがあることがわかりました。引き続き strace
コマンドを使用してゴルーチンの 1 つをトレースしました。その後、問題が見つかりました。ゴルーチンがパニックを発生させ、そのパニックが処理されないため、プロセス全体がクラッシュします。
コードを確認すると、このパニックはファイルの削除が原因であることがわかりましたが、コードではこのエラーが処理されませんでした。 goroutine パニックが処理されない場合、プロセス全体がクラッシュするため、プロセスが自動的に消滅します。
この問題を解決するには、パニックを処理してプロセス全体のクラッシュを防ぐ必要があります。必要に応じて回復関数を使用してパニックをキャプチャし、それを処理してプロセスのクラッシュを回避できます。
以下はパニックを処理するためのコード例です:
defer func() { if r := recover(); r != nil { log.Errorf("goroutine panic: %v", r) // TODO: 处理 panic } }() // 代码片段
defer 関数を使用すると、ゴルーチンが終了すると、たとえパニックが発生したとしても、それをキャプチャしてそれに応じて処理できます。単にパニック情報を出力するだけですが、実際には、アラートの送信やエラーに関する詳細情報のログ記録など、他の処理をここで実行することもできます。
Golang コードを作成する場合、ゴルーチンの特殊な性質により、ゴルーチンがパニックになると、プロセス全体がクラッシュする可能性があります。したがって、コードを記述するときは、この状況を考慮して、この状況に対処するコードを記述する必要があります。コードにパニック処理を追加することは非常に重要です。これは、運用環境での同様の問題を回避するのに役立ちます。
以上がgolangのプロセスが勝手に消えてしまうの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。