github.com/TeaOSLab/EdgeNode@v1.3.8/internal/utils/service_linux.go (about) 1 //go:build linux 2 // +build linux 3 4 package utils 5 6 import ( 7 "errors" 8 "fmt" 9 teaconst "github.com/TeaOSLab/EdgeNode/internal/const" 10 executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec" 11 "github.com/iwind/TeaGo/Tea" 12 "github.com/iwind/TeaGo/files" 13 "os" 14 "os/exec" 15 "regexp" 16 "time" 17 ) 18 19 var systemdServiceFile = "/etc/systemd/system/edge-node.service" 20 var initServiceFile = "/etc/init.d/" + teaconst.SystemdServiceName 21 22 // Install 安装服务 23 func (this *ServiceManager) Install(exePath string, args []string) error { 24 if os.Getgid() != 0 { 25 return errors.New("only root users can install the service") 26 } 27 28 systemd, err := executils.LookPath("systemctl") 29 if err != nil { 30 return this.installInitService(exePath, args) 31 } 32 33 return this.installSystemdService(systemd, exePath, args) 34 } 35 36 // Start 启动服务 37 func (this *ServiceManager) Start() error { 38 if os.Getgid() != 0 { 39 return errors.New("only root users can start the service") 40 } 41 42 if files.NewFile(systemdServiceFile).Exists() { 43 systemd, err := executils.LookPath("systemctl") 44 if err != nil { 45 return err 46 } 47 48 return exec.Command(systemd, "start", teaconst.SystemdServiceName+".service").Start() 49 } 50 return exec.Command("service", teaconst.ProcessName, "start").Start() 51 } 52 53 // Uninstall 删除服务 54 func (this *ServiceManager) Uninstall() error { 55 if os.Getgid() != 0 { 56 return errors.New("only root users can uninstall the service") 57 } 58 59 if files.NewFile(systemdServiceFile).Exists() { 60 systemd, err := executils.LookPath("systemctl") 61 if err != nil { 62 return err 63 } 64 65 // disable service 66 _ = executils.NewTimeoutCmd(10*time.Second, systemd, "disable", teaconst.SystemdServiceName+".service").Start() 67 68 // reload 69 _ = executils.NewTimeoutCmd(10*time.Second, systemd, "daemon-reload").Start() 70 71 return files.NewFile(systemdServiceFile).Delete() 72 } 73 74 f := files.NewFile(initServiceFile) 75 if f.Exists() { 76 return f.Delete() 77 } 78 return nil 79 } 80 81 // install init service 82 func (this *ServiceManager) installInitService(exePath string, args []string) error { 83 shortName := teaconst.SystemdServiceName 84 scriptFile := Tea.Root + "/scripts/" + shortName 85 if !files.NewFile(scriptFile).Exists() { 86 return errors.New("'scripts/" + shortName + "' file not exists") 87 } 88 89 data, err := os.ReadFile(scriptFile) 90 if err != nil { 91 return err 92 } 93 94 data = regexp.MustCompile("INSTALL_DIR=.+").ReplaceAll(data, []byte("INSTALL_DIR="+Tea.Root)) 95 err = os.WriteFile(initServiceFile, data, 0777) 96 if err != nil { 97 return err 98 } 99 100 chkCmd, err := executils.LookPath("chkconfig") 101 if err != nil { 102 return err 103 } 104 105 err = exec.Command(chkCmd, "--add", teaconst.ProcessName).Start() 106 if err != nil { 107 return err 108 } 109 110 return nil 111 } 112 113 // install systemd service 114 func (this *ServiceManager) installSystemdService(systemd, exePath string, args []string) error { 115 var shortName = teaconst.SystemdServiceName 116 var longName = "GoEdge Node" // TODO 将来可以修改 117 118 var startCmd = exePath + " daemon" 119 bashPath, _ := executils.LookPath("bash") 120 if len(bashPath) > 0 { 121 startCmd = bashPath + " -c \"" + startCmd + "\"" 122 } 123 124 var desc = `### BEGIN INIT INFO 125 # Provides: ` + shortName + ` 126 # Required-Start: $all 127 # Required-Stop: 128 # Default-Start: 2 3 4 5 129 # Default-Stop: 130 # Short-Description: ` + longName + ` Service 131 ### END INIT INFO 132 133 [Unit] 134 Description=` + longName + ` Service 135 Before=shutdown.target 136 After=network-online.target 137 138 [Service] 139 Type=simple 140 Restart=always 141 RestartSec=1s 142 ExecStart=` + startCmd + ` 143 ExecStop=` + exePath + ` stop 144 ExecReload=` + exePath + ` reload 145 146 [Install] 147 WantedBy=multi-user.target` 148 149 // write file 150 err := os.WriteFile(systemdServiceFile, []byte(desc), 0777) 151 if err != nil { 152 return err 153 } 154 155 // stop current systemd service if running 156 _ = executils.NewTimeoutCmd(10*time.Second, systemd, "stop", shortName+".service").Start() 157 158 // reload 159 _ = executils.NewTimeoutCmd(10*time.Second, systemd, "daemon-reload").Start() 160 161 // enable 162 var cmd = executils.NewTimeoutCmd(10*time.Second, systemd, "enable", shortName+".service") 163 cmd.WithStderr() 164 err = cmd.Run() 165 if err != nil { 166 return fmt.Errorf("%w: %s", err, cmd.Stderr()) 167 } 168 return nil 169 }