main.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "os/signal"
  6. "path"
  7. "runtime/pprof"
  8. "syscall"
  9. "time"
  10. "github.com/tal-tech/go-zero/core/cmdline"
  11. "github.com/tal-tech/go-zero/core/logx"
  12. )
  13. const (
  14. goroutineProfile = "goroutine"
  15. debugLevel = 2
  16. timeFormat = "0102150405"
  17. )
  18. func init() {
  19. go func() {
  20. // https://golang.org/pkg/os/signal/#Notify
  21. signals := make(chan os.Signal, 1)
  22. signal.Notify(signals, syscall.SIGUSR1, syscall.SIGTERM)
  23. for {
  24. v := <-signals
  25. switch v {
  26. case syscall.SIGUSR1:
  27. dumpGoroutines()
  28. case syscall.SIGTERM:
  29. gracefulStop(signals)
  30. default:
  31. logx.Error("Got unregistered signal:", v)
  32. }
  33. }
  34. }()
  35. }
  36. func dumpGoroutines() {
  37. command := path.Base(os.Args[0])
  38. pid := syscall.Getpid()
  39. dumpFile := path.Join(os.TempDir(), fmt.Sprintf("%s-%d-goroutines-%s.dump",
  40. command, pid, time.Now().Format(timeFormat)))
  41. logx.Infof("Got dump goroutine signal, printing goroutine profile to %s", dumpFile)
  42. if f, err := os.Create(dumpFile); err != nil {
  43. logx.Errorf("Failed to dump goroutine profile, error: %v", err)
  44. } else {
  45. defer f.Close()
  46. pprof.Lookup(goroutineProfile).WriteTo(f, debugLevel)
  47. }
  48. }
  49. func gracefulStop(signals chan os.Signal) {
  50. signal.Stop(signals)
  51. logx.Info("Got signal SIGTERM, shutting down...")
  52. time.Sleep(time.Second * 5)
  53. logx.Infof("Still alive after %v, going to force kill the process...", time.Second*5)
  54. syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
  55. }
  56. func main() {
  57. cmdline.EnterToContinue()
  58. }