main.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. package main
  2. import (
  3. "context"
  4. "errors"
  5. "flag"
  6. "fmt"
  7. "net/http"
  8. "os"
  9. "strings"
  10. "time"
  11. "rtu_linux_services/servicelib"
  12. "github.com/kardianos/service"
  13. "hnyfkj.com.cn/rtu/linux/baseapp"
  14. "hnyfkj.com.cn/rtu/linux/netmgrd"
  15. "hnyfkj.com.cn/rtu/linux/utils/jsonrpc2"
  16. )
  17. var (
  18. Version = "0.0.0.1"
  19. BuildTime = ""
  20. )
  21. const (
  22. network = "tcp" // http -> tcp
  23. listenAddr = "127.0.0.1:7000"
  24. )
  25. type program struct {
  26. name string
  27. core_server *jsonrpc2.RPCServer
  28. http_server *http.Server
  29. }
  30. // Start should not block. Do the actual work async.
  31. func (p *program) Start(s service.Service) error {
  32. logCfgFile, err := servicelib.EnsureDefaultLogConfig()
  33. if err != nil {
  34. return err
  35. }
  36. baseapp.InitLogger(logCfgFile)
  37. baseapp.Logger.Infof("App Version: %s, Build Time: %s", Version, BuildTime)
  38. if !netmgrd.ModemInit() {
  39. return errors.New("modem init failed")
  40. }
  41. go writeDeviceIMEI() // 异步获取IMEI号并写入文件, 用于YFKJ SSHD远程运维服务的设备标识
  42. netmgrd.SetTimeSyncEnabled(false) // -> "timesyncd.service"
  43. netmgrd.ModuleInit()
  44. p.core_server, err = jsonrpc2.NewRPCServer(p.name, baseapp.Logger)
  45. if err != nil {
  46. return err
  47. }
  48. methods := make(jsonrpc2.MethodMap)
  49. //////////////////////////////////////////////////////////
  50. _getBuildVer := servicelib.MakeGetBuildVer(
  51. Version, BuildTime)
  52. methods["basic.getBuildVer"] = _getBuildVer // 获取软件版本
  53. _getLogLevel := servicelib.GetLogLevel
  54. methods["basic.getLogLevel"] = _getLogLevel // 获取日志级别
  55. _setLogLevel := servicelib.SetLogLevel
  56. methods["basic.setLogLevel"] = _setLogLevel // 设置日志级别
  57. _saveLogConf := servicelib.SaveLogConf
  58. methods["basic.saveLogConf"] = _saveLogConf // 保存日志设置
  59. //////////////////////////////////////////////////////////
  60. methods["core.getModemInfo"] = getModemInfo // IMEI、ICCID
  61. methods["core.getNetStatus"] = getNetStatus // 联网状态信息
  62. //////////////////////////////////////////////////////////
  63. err = p.core_server.RegisterMethods(methods)
  64. if err != nil {
  65. return err
  66. }
  67. mux := http.NewServeMux()
  68. mux.Handle("/rpc", p.core_server)
  69. p.http_server = &http.Server{
  70. Addr: listenAddr,
  71. Handler: mux,
  72. }
  73. go p.run()
  74. return nil
  75. }
  76. // Do work here
  77. func (p *program) run() {
  78. baseapp.Logger.Infof(
  79. "[%s] Http server starting on %s...",
  80. p.name,
  81. p.http_server.Addr,
  82. )
  83. err := p.http_server.ListenAndServe() // 同步阻塞
  84. if err != nil && !errors.Is(err, http.ErrServerClosed) {
  85. baseapp.Logger.Errorf("[%s] Start http server error: %v!!", p.name, err)
  86. return
  87. }
  88. }
  89. // Stop should not block. Return with a few seconds.
  90. func (p *program) Stop(s service.Service) error {
  91. if p.core_server != nil {
  92. p.core_server.Stop()
  93. }
  94. if p.http_server != nil {
  95. ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
  96. defer cancel()
  97. _ = p.http_server.Shutdown(ctx)
  98. }
  99. netmgrd.ModemExit()
  100. baseapp.ExitLogger()
  101. return nil
  102. }
  103. func main() {
  104. baseapp.SetOptDirs(true, true, false, false)
  105. baseapp.InitPath()
  106. svcFlag := flag.String("service", "", "Control the system service.")
  107. flag.Parse()
  108. svcConfig := &service.Config{
  109. Name: "yfkj-networkd",
  110. DisplayName: "yfkj-networkd",
  111. Description: "Network connectivity management",
  112. Option: map[string]any{
  113. "Restart": "always", // 无条件重启
  114. },
  115. }
  116. servicelib.WriteVersionFile(baseapp.EXEC_DIR, Version) //-> for 升级
  117. prg := &program{
  118. name: "NetworkManager",
  119. }
  120. svc, err := service.New(prg, svcConfig)
  121. if err != nil {
  122. fmt.Printf("%s.service creation failed: %v\n",
  123. svcConfig.Name, err)
  124. os.Exit(1)
  125. }
  126. if len(*svcFlag) != 0 {
  127. err := service.Control(svc, *svcFlag)
  128. if err != nil {
  129. fmt.Printf("%v\n Valid actions: %q\n", err, service.ControlAction)
  130. }
  131. os.Exit(0)
  132. }
  133. if servicelib.IsAddrInUse(network, listenAddr) { // 查询端口占用,避免运行多份实例
  134. fmt.Printf(
  135. "%s.service start failed: listen addr %s already in use\n",
  136. svcConfig.Name, listenAddr,
  137. )
  138. os.Exit(1)
  139. }
  140. if err := svc.Run(); err != nil {
  141. fmt.Printf("%s.service run failed: %v\n",
  142. svcConfig.Name, err)
  143. os.Exit(1)
  144. }
  145. }
  146. func writeDeviceIMEI() {
  147. const path = "/var/device_imei.txt"
  148. tmp := path + ".tmp"
  149. for {
  150. imei := strings.TrimSpace(netmgrd.GetIMEI())
  151. if imei == "" || imei == netmgrd.ErrUnknownModemTypeMsg {
  152. time.Sleep(time.Second)
  153. continue
  154. }
  155. if old, err := os.ReadFile(path); err == nil && strings.TrimSpace(string(old)) == imei {
  156. return
  157. }
  158. if os.WriteFile(tmp, []byte(imei+"\n"), 0644) == nil {
  159. _ = os.Rename(tmp, path)
  160. }
  161. return
  162. }
  163. }