main.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. package main
  2. import (
  3. "fmt"
  4. go_lazy_quiter "git.swzry.com/zry/go-lazy-quiter"
  5. "git.swzry.com/zry/pathutils"
  6. "gopkg.in/natefinch/lumberjack.v2"
  7. "gopkg.in/yaml.v2"
  8. "io"
  9. "io/ioutil"
  10. "os"
  11. "os/exec"
  12. "sync"
  13. )
  14. var ConfigData ConfigYAML
  15. var FrontendShellLogger *lumberjack.Logger
  16. var BackendShellLogger *lumberjack.Logger
  17. var mainWaitGroup sync.WaitGroup
  18. var lazyQuiter *go_lazy_quiter.LazyQuiter
  19. var pFrontend *os.Process
  20. var pBackend *os.Process
  21. func main() {
  22. fmt.Println("zDWSI Launcher Start.")
  23. CheckInit()
  24. LoadYAML()
  25. SetSignalCatcher()
  26. StartFrontend()
  27. StartBackend()
  28. fmt.Println("Launcher Sleeping.")
  29. RoutineSleep()
  30. }
  31. func SetSignalCatcher() {
  32. lazyQuiter = go_lazy_quiter.NewLazyQuiter(os.Kill)
  33. go func() {
  34. lazyQuiter.Wait()
  35. if pFrontend != nil {
  36. _ = pFrontend.Signal(os.Kill)
  37. }
  38. if pBackend != nil {
  39. _ = pBackend.Signal(os.Kill)
  40. }
  41. }()
  42. }
  43. func CheckInit() {
  44. pe, err := pathutils.PathExists("/data/config.yaml")
  45. if err == nil && pe {
  46. return
  47. }
  48. fmt.Println("Initializing Container...")
  49. pathutils.MkDirIfNotExist("/data/frontend/", 0777)
  50. pathutils.MkDirIfNotExist("/data/backend/", 0777)
  51. pathutils.MkDirIfNotExist("/data/wwwroot/", 0777)
  52. pathutils.MkDirIfNotExist("/data/logs/", 0777)
  53. pathutils.CopyFile("/data/config.yaml", "/rel/config.default.yaml")
  54. pathutils.CopyFile("/data/wwwroot/index.html", "/rel/index.default.html")
  55. pathutils.CopyFile("/data/frontend/zDWSIFrontend", "/rel/zDWSIFrontend_linux")
  56. pathutils.CopyFile("/data/backend/Backend", "/rel/zDWSIBlankBackend_linux")
  57. pathutils.CopyFile("/data/frontend/zdwsi.frontend.config.yaml", "/rel/zdwsi.frontend.config.default.yaml")
  58. os.Chmod("/data/frontend/zDWSIFrontend", 0755)
  59. os.Chmod("/data/backend/Backend", 0755)
  60. fmt.Println("Container Initialized. Please Edit 'config.yaml'.")
  61. }
  62. func LoadYAML() {
  63. fmt.Println("Load Config '/data/config.yaml'")
  64. jdata, err := ioutil.ReadFile("/data/config.yaml")
  65. if err != nil {
  66. fmt.Println("failed read file 'config.yaml': ", err)
  67. Dead()
  68. }
  69. err = yaml.Unmarshal(jdata, &ConfigData)
  70. if err != nil {
  71. fmt.Println("failed parse 'config.yaml': ", err)
  72. Dead()
  73. }
  74. fmt.Println("Config Loaded.")
  75. }
  76. func Dead() {
  77. fmt.Println("Program Dead By Fatal Error. Please Restart.")
  78. FailureServer()
  79. }
  80. func RoutineSleep() {
  81. mainWaitGroup.Wait()
  82. fmt.Println("All GoRoutine Stopped. Please Restart.")
  83. FailureServer()
  84. }
  85. func InitLogger(cfg LumberjackLoggerYAML) *lumberjack.Logger {
  86. ljl := &lumberjack.Logger{
  87. Filename: cfg.FileName,
  88. MaxSize: cfg.MaxSize,
  89. MaxAge: cfg.MaxAge,
  90. MaxBackups: cfg.MaxBackups,
  91. LocalTime: cfg.UseLocalTime,
  92. Compress: cfg.Compress,
  93. }
  94. return ljl
  95. }
  96. func StartFrontend() {
  97. if !ConfigData.Frontend.Enable {
  98. fmt.Println("Frontend Not Enable.")
  99. return
  100. }
  101. pe, err := pathutils.PathExists(ConfigData.Frontend.EntryPoint)
  102. if err != nil || !pe {
  103. fmt.Println("frontend entrypoint not exists")
  104. return
  105. }
  106. FrontendShellLogger = InitLogger(ConfigData.Frontend.ShellLog)
  107. mainWaitGroup.Add(1)
  108. go func() {
  109. runenv := make([]string, 0)
  110. runenv = append(runenv, makeEnvMember("listen", ConfigData.Frontend.ListenAddr))
  111. runenv = append(runenv, makeEnvMember("wwwroot", ConfigData.Frontend.WWWRoot))
  112. runenv = append(runenv, makeEnvMember("backend_prefix", ConfigData.Frontend.BackendProxy.Prefix))
  113. runenv = append(runenv, makeEnvMember("backend_target", ConfigData.Frontend.BackendProxy.ProxyTaret))
  114. err = StartProcess(ConfigData.Frontend.EntryPoint, runenv, FrontendShellLogger, "frontend")
  115. if err != nil {
  116. fmt.Println("failed start frontend or frontend exited with error: ", err)
  117. }
  118. mainWaitGroup.Done()
  119. }()
  120. }
  121. func makeEnvMember(key string, value string) string {
  122. return fmt.Sprintf("%s=%s", key, value)
  123. }
  124. func StartBackend() {
  125. if !ConfigData.Backend.Enable {
  126. fmt.Println("Backend Not Enable.")
  127. return
  128. }
  129. pe, err := pathutils.PathExists(ConfigData.Backend.EntryPoint)
  130. if err != nil || !pe {
  131. fmt.Println("backend entrypoint not exists")
  132. return
  133. }
  134. BackendShellLogger = InitLogger(ConfigData.Backend.ShellLog)
  135. mainWaitGroup.Add(1)
  136. go func() {
  137. runenv := make([]string, 0)
  138. runenv = append(runenv, makeEnvMember("listen", ConfigData.Backend.ListenAddr))
  139. err = StartProcess(ConfigData.Backend.EntryPoint, runenv, BackendShellLogger, "backend")
  140. if err != nil {
  141. fmt.Println("failed start backend or backend exited with error: ", err)
  142. }
  143. mainWaitGroup.Done()
  144. }()
  145. }
  146. func StartProcess(entry string, runenv []string, logger io.Writer, ptype string) error {
  147. cmd := exec.Command(entry)
  148. cmd.Env = runenv
  149. pipe_r, pipe_w := io.Pipe()
  150. cmd.Stdout = pipe_w
  151. cmd.Stderr = pipe_w
  152. go func() {
  153. io.Copy(logger, pipe_r)
  154. }()
  155. err := cmd.Start()
  156. switch ptype {
  157. case "frontend":
  158. pFrontend = cmd.Process
  159. break
  160. case "backend":
  161. pBackend = cmd.Process
  162. break
  163. }
  164. if err != nil {
  165. return err
  166. }
  167. err = cmd.Wait()
  168. return err
  169. }