github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zutil/daemon/daemon_freebsd.go (about) 1 package daemon 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "text/template" 9 ) 10 11 type ( 12 freebsdRcdService struct { 13 i Iface 14 *Config 15 userService bool 16 } 17 freebsdSystem struct{} 18 ) 19 20 const version = "freebsd-rcd" 21 22 var interactive = false 23 24 func init() { 25 var err error 26 chooseSystem(freebsdSystem{}) 27 interactive, err = isInteractive() 28 if err != nil { 29 panic(err) 30 } 31 } 32 33 func (freebsdSystem) String() string { 34 return version 35 } 36 37 func (freebsdSystem) Detect() bool { 38 return true 39 } 40 41 func (freebsdSystem) Interactive() bool { 42 return interactive 43 } 44 45 func (freebsdSystem) New(i Iface, c *Config) (ServiceIface, error) { 46 userService := optionUserServiceDefault 47 if s, ok := c.Options[optionUserService]; ok { 48 userService, _ = s.(bool) 49 } 50 51 if c.Context == nil { 52 c.Context = context.Background() 53 } 54 55 s := &freebsdRcdService{ 56 i: i, 57 Config: c, 58 userService: userService, 59 } 60 return s, nil 61 } 62 63 func isInteractive() (bool, error) { 64 return os.Getppid() != 1, nil 65 } 66 67 func (s *freebsdRcdService) Status() string { 68 return "Unknown" 69 } 70 71 func (s *freebsdRcdService) String() string { 72 if len(s.DisplayName) > 0 { 73 return s.DisplayName 74 } 75 return s.Name 76 } 77 78 func (s *freebsdRcdService) getServiceFilePath() (string, error) { 79 80 return "/etc/rc.d/" + s.Name, nil 81 } 82 83 func (s *freebsdRcdService) Install() error { 84 confPath, err := s.getServiceFilePath() 85 if err != nil { 86 return err 87 } 88 _, err = os.Stat(confPath) 89 if err == nil { 90 return fmt.Errorf("init already exists: %s", confPath) 91 } 92 93 if s.userService { 94 // ~/Library/LaunchAgents exists. 95 err = os.MkdirAll(filepath.Dir(confPath), 0700) 96 if err != nil { 97 return err 98 } 99 } 100 101 f, err := os.Create(confPath) 102 if err != nil { 103 return err 104 } 105 defer f.Close() 106 107 keepAlive := optionKeepAliveDefault 108 if v, ok := s.Options[optionKeepAlive]; ok { 109 keepAlive, _ = v.(bool) 110 } 111 load := isServiceRestart(s.Config) 112 sessionCreate := optionSessionCreateDefault 113 if v, ok := s.Options[optionSessionCreate]; ok { 114 sessionCreate, _ = v.(bool) 115 } 116 117 path := s.execPath() 118 to := &struct { 119 *Config 120 Path string 121 122 KeepAlive, RunAtLoad bool 123 SessionCreate bool 124 }{ 125 Config: s.Config, 126 Path: path, 127 KeepAlive: keepAlive, 128 RunAtLoad: load, 129 SessionCreate: sessionCreate, 130 } 131 132 functions := template.FuncMap{ 133 "bool": func(v bool) string { 134 if v { 135 return "true" 136 } 137 return "false" 138 }, 139 } 140 141 rcdScript := "" 142 if s.Name == "opsramp-agent" { 143 rcdScript = rcdScriptOpsrampAgent 144 file, err := os.OpenFile("/etc/rc.conf", os.O_WRONLY|os.O_APPEND, 0644) 145 if err != nil { 146 return err 147 } 148 defer file.Close() 149 data := "opsramp_agent_enable=" + `"` + "YES" + `"` 150 _, _ = fmt.Fprintln(file, data) 151 152 } else if s.Name == "opsramp-shield" { 153 rcdScript = rcdScriptOpsrampShield 154 file, err := os.OpenFile("/etc/rc.conf", os.O_WRONLY|os.O_APPEND, 0644) 155 if err != nil { 156 return err 157 } 158 defer file.Close() 159 data := "opsramp_shield_enable=" + `"` + "YES" + `"` 160 _, _ = fmt.Fprintln(file, data) 161 162 } else { 163 rcdScript = rcdScriptAgentUninstall 164 file, err := os.OpenFile("/etc/rc.conf", os.O_WRONLY|os.O_APPEND, 0644) 165 if err != nil { 166 fmt.Printf("failed opening file: %s\n", err) 167 } 168 defer file.Close() 169 data := "agent_uninstall_enable=" + `"` + "YES" + `"` 170 _, _ = fmt.Fprintln(file, data) 171 } 172 173 t := template.Must(template.New("rcdScript").Funcs(functions).Parse(rcdScript)) 174 errExecute := t.Execute(f, to) 175 176 serviceName := "/etc/rc.d/" + s.Name 177 err = os.Chmod(serviceName, 755) 178 if err != nil { 179 return err 180 } 181 182 return errExecute 183 } 184 185 func (s *freebsdRcdService) Uninstall() error { 186 _ = s.Stop() 187 if s.Name == "opsramp-agent" { 188 _ = run("sed", "-i", "-e", "'/opsramp_agent_enable/d'", "/etc/rc.conf") 189 } else if s.Name == "opsramp-shield" { 190 _ = run("sed", "-i", "-e", "'/opsramp_shield_enable/d'", "/etc/rc.conf") 191 } else { 192 _ = run("sed", "-i", "-e", "'/agent_uninstall_enable/d'", "/etc/rc.conf") 193 } 194 confPath, err := s.getServiceFilePath() 195 if err != nil { 196 return err 197 } 198 return os.Remove(confPath) 199 } 200 201 func (s *freebsdRcdService) Start() error { 202 return run("service", s.Name, "start") 203 } 204 func (s *freebsdRcdService) Stop() error { 205 return run("service", s.Name, "stop") 206 207 } 208 func (s *freebsdRcdService) Restart() error { 209 return run("service", s.Name, "restart") 210 211 } 212 213 func (s *freebsdRcdService) Run() error { 214 var err error 215 216 err = s.i.Start(s) 217 if err != nil { 218 return err 219 } 220 runWait := func() { 221 select { 222 case <-SingleKillSignal(): 223 case <-s.Config.Context.Done(): 224 } 225 } 226 if v, ok := s.Options[optionRunWait]; ok { 227 runWait, _ = v.(func()) 228 } 229 runWait() 230 return s.i.Stop(s) 231 } 232 233 const rcdScriptOpsrampAgent = `. /etc/rc.subr 234 235 name="opsramp_agent" 236 rcvar="opsramp_agent_enable" 237 command="/opt/opsramp/agent/opsramp-agent service" 238 pidfile="/var/run/${name}.pid" 239 240 start_cmd="test_start" 241 stop_cmd="test_stop" 242 status_cmd="test_status" 243 244 test_start() { 245 /usr/sbin/daemon -p ${pidfile} ${command} 246 } 247 248 test_status() { 249 if [ -e ${pidfile} ]; then 250 echo ${name} is running... 251 else 252 echo ${name} is not running. 253 fi 254 } 255 256 test_stop() { 257 if [ -e ${pidfile} ]; then 258 ` + 259 " kill `cat ${pidfile}`; " + 260 ` 261 else 262 echo ${name} is not running? 263 fi 264 } 265 266 load_rc_config $name 267 run_rc_command "$1" 268 ` 269 270 const rcdScriptOpsrampShield = `. /etc/rc.subr 271 272 name="opsramp_shield" 273 rcvar="opsramp_shield_enable" 274 command="/opt/opsramp/agent/bin/opsramp-shield service" 275 pidfile="/var/run/${name}.pid" 276 277 start_cmd="test_start" 278 stop_cmd="test_stop" 279 status_cmd="test_status" 280 281 test_start() { 282 /usr/sbin/daemon -p ${pidfile} ${command} 283 } 284 285 test_status() { 286 if [ -e ${pidfile} ]; then 287 echo ${name} is running... 288 else 289 echo ${name} is not running. 290 fi 291 } 292 293 test_stop() { 294 if [ -e ${pidfile} ]; then 295 ` + 296 " kill `cat ${pidfile}`; " + 297 ` 298 else 299 echo ${name} is not running? 300 fi 301 } 302 303 load_rc_config $name 304 run_rc_command "$1" 305 ` 306 const rcdScriptAgentUninstall = `. /etc/rc.subr 307 308 name="agent_uninstall" 309 rcvar="agent_uninstall_enable" 310 command="/opt/opsramp/agent/bin/uninstall" 311 pidfile="/var/run/${name}.pid" 312 313 start_cmd="test_start" 314 stop_cmd="test_stop" 315 status_cmd="test_status" 316 317 test_start() { 318 /usr/sbin/daemon -p ${pidfile} ${command} 319 } 320 321 test_status() { 322 if [ -e ${pidfile} ]; then 323 echo ${name} is running... 324 else 325 echo ${name} is not running. 326 fi 327 } 328 329 test_stop() { 330 if [ -e ${pidfile} ]; then 331 ` + 332 " kill `cat ${pidfile}`; " + 333 ` 334 else 335 echo ${name} is not running? 336 fi 337 } 338 339 load_rc_config $name 340 run_rc_command "$1" 341 `