server.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. package cmd
  2. import (
  3. "context"
  4. "fmt"
  5. "net/http"
  6. "os"
  7. "os/signal"
  8. "syscall"
  9. "github.com/spf13/cobra"
  10. "github.com/spf13/viper"
  11. "github.com/usememos/memos/server"
  12. _profile "github.com/usememos/memos/server/profile"
  13. )
  14. const (
  15. greetingBanner = `
  16. ███╗ ███╗███████╗███╗ ███╗ ██████╗ ███████╗
  17. ████╗ ████║██╔════╝████╗ ████║██╔═══██╗██╔════╝
  18. ██╔████╔██║█████╗ ██╔████╔██║██║ ██║███████╗
  19. ██║╚██╔╝██║██╔══╝ ██║╚██╔╝██║██║ ██║╚════██║
  20. ██║ ╚═╝ ██║███████╗██║ ╚═╝ ██║╚██████╔╝███████║
  21. ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝
  22. `
  23. )
  24. var (
  25. profile *_profile.Profile
  26. mode string
  27. port int
  28. data string
  29. rootCmd = &cobra.Command{
  30. Use: "memos",
  31. Short: `An open-source, self-hosted memo hub with knowledge management and social networking.`,
  32. Run: func(_cmd *cobra.Command, _args []string) {
  33. ctx, cancel := context.WithCancel(context.Background())
  34. s, err := server.NewServer(ctx, profile)
  35. if err != nil {
  36. cancel()
  37. fmt.Printf("failed to create server, error: %+v\n", err)
  38. return
  39. }
  40. c := make(chan os.Signal, 1)
  41. // Trigger graceful shutdown on SIGINT or SIGTERM.
  42. // The default signal sent by the `kill` command is SIGTERM,
  43. // which is taken as the graceful shutdown signal for many systems, eg., Kubernetes, Gunicorn.
  44. signal.Notify(c, os.Interrupt, syscall.SIGTERM)
  45. go func() {
  46. sig := <-c
  47. fmt.Printf("%s received.\n", sig.String())
  48. s.Shutdown(ctx)
  49. cancel()
  50. }()
  51. println(greetingBanner)
  52. fmt.Printf("Version %s has started at :%d\n", profile.Version, profile.Port)
  53. if err := s.Start(ctx); err != nil {
  54. if err != http.ErrServerClosed {
  55. fmt.Printf("failed to start server, error: %+v\n", err)
  56. cancel()
  57. }
  58. }
  59. // Wait for CTRL-C.
  60. <-ctx.Done()
  61. },
  62. }
  63. )
  64. func Execute() error {
  65. return rootCmd.Execute()
  66. }
  67. func init() {
  68. cobra.OnInitialize(initConfig)
  69. rootCmd.PersistentFlags().StringVarP(&mode, "mode", "m", "demo", `mode of server, can be "prod" or "dev" or "demo"`)
  70. rootCmd.PersistentFlags().IntVarP(&port, "port", "p", 8081, "port of server")
  71. rootCmd.PersistentFlags().StringVarP(&data, "data", "d", "", "data directory")
  72. err := viper.BindPFlag("mode", rootCmd.PersistentFlags().Lookup("mode"))
  73. if err != nil {
  74. panic(err)
  75. }
  76. err = viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port"))
  77. if err != nil {
  78. panic(err)
  79. }
  80. err = viper.BindPFlag("data", rootCmd.PersistentFlags().Lookup("data"))
  81. if err != nil {
  82. panic(err)
  83. }
  84. viper.SetDefault("mode", "demo")
  85. viper.SetDefault("port", 8081)
  86. viper.SetEnvPrefix("memos")
  87. }
  88. func initConfig() {
  89. viper.AutomaticEnv()
  90. var err error
  91. profile, err = _profile.GetProfile()
  92. if err != nil {
  93. fmt.Printf("failed to get profile, error: %+v\n", err)
  94. return
  95. }
  96. println("---")
  97. println("Server profile")
  98. println("dsn:", profile.DSN)
  99. println("port:", profile.Port)
  100. println("mode:", profile.Mode)
  101. println("version:", profile.Version)
  102. println("---")
  103. }