package main import ( "context" "errors" "flag" "fmt" "net/http" "os" "strings" "time" "rtu_linux_services/servicelib" "github.com/kardianos/service" "hnyfkj.com.cn/rtu/linux/baseapp" "hnyfkj.com.cn/rtu/linux/netmgrd" "hnyfkj.com.cn/rtu/linux/utils/jsonrpc2" ) var ( Version = "0.0.0.1" BuildTime = "" ) const ( network = "tcp" // http -> tcp listenAddr = "127.0.0.1:7000" ) type program struct { name string core_server *jsonrpc2.RPCServer http_server *http.Server } // Start should not block. Do the actual work async. func (p *program) Start(s service.Service) error { logCfgFile, err := servicelib.EnsureDefaultLogConfig() if err != nil { return err } baseapp.InitLogger(logCfgFile) baseapp.Logger.Infof("App Version: %s, Build Time: %s", Version, BuildTime) if !netmgrd.ModemInit() { return errors.New("modem init failed") } go writeDeviceIMEI() // 异步获取IMEI号并写入文件, 用于YFKJ SSHD远程运维服务的设备标识 netmgrd.SetTimeSyncEnabled(false) // -> "timesyncd.service" netmgrd.ModuleInit() p.core_server, err = jsonrpc2.NewRPCServer(p.name, baseapp.Logger) if err != nil { return err } methods := make(jsonrpc2.MethodMap) ////////////////////////////////////////////////////////// _getBuildVer := servicelib.MakeGetBuildVer( Version, BuildTime) methods["basic.getBuildVer"] = _getBuildVer // 获取软件版本 _getLogLevel := servicelib.GetLogLevel methods["basic.getLogLevel"] = _getLogLevel // 获取日志级别 _setLogLevel := servicelib.SetLogLevel methods["basic.setLogLevel"] = _setLogLevel // 设置日志级别 _saveLogConf := servicelib.SaveLogConf methods["basic.saveLogConf"] = _saveLogConf // 保存日志设置 ////////////////////////////////////////////////////////// methods["core.getModemInfo"] = getModemInfo // IMEI、ICCID methods["core.getNetStatus"] = getNetStatus // 联网状态信息 ////////////////////////////////////////////////////////// err = p.core_server.RegisterMethods(methods) if err != nil { return err } mux := http.NewServeMux() mux.Handle("/rpc", p.core_server) p.http_server = &http.Server{ Addr: listenAddr, Handler: mux, } go p.run() return nil } // Do work here func (p *program) run() { baseapp.Logger.Infof( "[%s] Http server starting on %s...", p.name, p.http_server.Addr, ) err := p.http_server.ListenAndServe() // 同步阻塞 if err != nil && !errors.Is(err, http.ErrServerClosed) { baseapp.Logger.Errorf("[%s] Start http server error: %v!!", p.name, err) return } } // Stop should not block. Return with a few seconds. func (p *program) Stop(s service.Service) error { if p.core_server != nil { p.core_server.Stop() } if p.http_server != nil { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() _ = p.http_server.Shutdown(ctx) } netmgrd.ModemExit() baseapp.ExitLogger() return nil } func main() { baseapp.SetOptDirs(true, true, false, false) baseapp.InitPath() svcFlag := flag.String("service", "", "Control the system service.") flag.Parse() svcConfig := &service.Config{ Name: "yfkj-networkd", DisplayName: "yfkj-networkd", Description: "Network connectivity management", Option: map[string]any{ "Restart": "always", // 无条件重启 }, } servicelib.WriteVersionFile(baseapp.EXEC_DIR, Version) //-> for 升级 prg := &program{ name: "NetworkManager", } svc, err := service.New(prg, svcConfig) if err != nil { fmt.Printf("%s.service creation failed: %v\n", svcConfig.Name, err) os.Exit(1) } if len(*svcFlag) != 0 { err := service.Control(svc, *svcFlag) if err != nil { fmt.Printf("%v\n Valid actions: %q\n", err, service.ControlAction) } os.Exit(0) } if servicelib.IsAddrInUse(network, listenAddr) { // 查询端口占用,避免运行多份实例 fmt.Printf( "%s.service start failed: listen addr %s already in use\n", svcConfig.Name, listenAddr, ) os.Exit(1) } if err := svc.Run(); err != nil { fmt.Printf("%s.service run failed: %v\n", svcConfig.Name, err) os.Exit(1) } } func writeDeviceIMEI() { const path = "/var/device_imei.txt" tmp := path + ".tmp" for { imei := strings.TrimSpace(netmgrd.GetIMEI()) if imei == "" || imei == netmgrd.ErrUnknownModemTypeMsg { time.Sleep(time.Second) continue } if old, err := os.ReadFile(path); err == nil && strings.TrimSpace(string(old)) == imei { return } if os.WriteFile(tmp, []byte(imei+"\n"), 0644) == nil { _ = os.Rename(tmp, path) } return } }