gitee.com/quant1x/gox@v1.21.2/daemon/daemon_freebsd.go (about) 1 // Copyright 2020 The Go Authors. All rights reserved. 2 // Use of this source code is governed by 3 // license that can be found in the LICENSE file. 4 5 package daemon 6 7 import ( 8 "fmt" 9 "io/ioutil" 10 "os" 11 "os/exec" 12 "path/filepath" 13 "regexp" 14 "strings" 15 "text/template" 16 ) 17 18 // systemVRecord - standard record (struct) for linux systemV version of daemon package 19 type bsdRecord struct { 20 name string 21 description string 22 kind Kind 23 dependencies []string 24 } 25 26 // Standard service path for systemV daemons 27 func (bsd *bsdRecord) servicePath() string { 28 return "/usr/local/etc/rc.d/" + bsd.name 29 } 30 31 // Is a service installed 32 func (bsd *bsdRecord) isInstalled() bool { 33 34 if _, err := os.Stat(bsd.servicePath()); err == nil { 35 return true 36 } 37 38 return false 39 } 40 41 // Is a service is enabled 42 func (bsd *bsdRecord) isEnabled() (bool, error) { 43 rcConf, err := os.Open("/etc/rc.conf") 44 if err != nil { 45 fmt.Println("Error opening file:", err) 46 return false, err 47 } 48 defer rcConf.Close() 49 rcData, _ := ioutil.ReadAll(rcConf) 50 r, _ := regexp.Compile(`.*` + bsd.name + `_enable="YES".*`) 51 v := string(r.Find(rcData)) 52 var chrFound, sharpFound bool 53 for _, c := range v { 54 if c == '#' && !chrFound { 55 sharpFound = true 56 break 57 } else if !sharpFound && c != ' ' { 58 chrFound = true 59 break 60 } 61 } 62 return chrFound, nil 63 } 64 65 func (bsd *bsdRecord) getCmd(cmd string) string { 66 if ok, err := bsd.isEnabled(); !ok || err != nil { 67 fmt.Println("Service is not enabled, using one" + cmd + " instead") 68 cmd = "one" + cmd 69 } 70 return cmd 71 } 72 73 // Get the daemon properly 74 func newDaemon(name, description string, kind Kind, dependencies []string) (Daemon, error) { 75 return &bsdRecord{name, description, kind, dependencies}, nil 76 } 77 78 func execPath() (name string, err error) { 79 name = os.Args[0] 80 if name[0] == '.' { 81 name, err = filepath.Abs(name) 82 if err == nil { 83 name = filepath.Clean(name) 84 } 85 } else { 86 name, err = exec.LookPath(filepath.Clean(name)) 87 } 88 return name, err 89 } 90 91 // Check service is running 92 func (bsd *bsdRecord) checkRunning() (string, bool) { 93 output, err := exec.Command("service", bsd.name, bsd.getCmd("status")).Output() 94 if err == nil { 95 if matched, err := regexp.MatchString(bsd.name, string(output)); err == nil && matched { 96 reg := regexp.MustCompile("pid ([0-9]+)") 97 data := reg.FindStringSubmatch(string(output)) 98 if len(data) > 1 { 99 return "Service (pid " + data[1] + ") is running...", true 100 } 101 return "Service is running...", true 102 } 103 } 104 105 return "Service is stopped", false 106 } 107 108 // Install the service 109 func (bsd *bsdRecord) Install(args ...string) (string, error) { 110 installAction := "Install " + bsd.description + ":" 111 112 if ok, err := checkPrivileges(); !ok { 113 return installAction + failed, err 114 } 115 116 srvPath := bsd.servicePath() 117 118 if bsd.isInstalled() { 119 return installAction + failed, ErrAlreadyInstalled 120 } 121 122 file, err := os.Create(srvPath) 123 if err != nil { 124 return installAction + failed, err 125 } 126 defer file.Close() 127 128 execPatch, err := executablePath(bsd.name) 129 if err != nil { 130 return installAction + failed, err 131 } 132 133 templ, err := template.New("bsdConfig").Parse(bsdConfig) 134 if err != nil { 135 return installAction + failed, err 136 } 137 138 if err := templ.Execute( 139 file, 140 &struct { 141 Name, Description, Path, Args string 142 }{bsd.name, bsd.description, execPatch, strings.Join(args, " ")}, 143 ); err != nil { 144 return installAction + failed, err 145 } 146 147 if err := os.Chmod(srvPath, 0755); err != nil { 148 return installAction + failed, err 149 } 150 151 return installAction + success, nil 152 } 153 154 // Remove the service 155 func (bsd *bsdRecord) Remove() (string, error) { 156 removeAction := "Removing " + bsd.description + ":" 157 158 if ok, err := checkPrivileges(); !ok { 159 return removeAction + failed, err 160 } 161 162 if !bsd.isInstalled() { 163 return removeAction + failed, ErrNotInstalled 164 } 165 166 if err := os.Remove(bsd.servicePath()); err != nil { 167 return removeAction + failed, err 168 } 169 170 return removeAction + success, nil 171 } 172 173 // Start the service 174 func (bsd *bsdRecord) Start() (string, error) { 175 startAction := "Starting " + bsd.description + ":" 176 177 if ok, err := checkPrivileges(); !ok { 178 return startAction + failed, err 179 } 180 181 if !bsd.isInstalled() { 182 return startAction + failed, ErrNotInstalled 183 } 184 185 if _, ok := bsd.checkRunning(); ok { 186 return startAction + failed, ErrAlreadyRunning 187 } 188 189 if err := exec.Command("service", bsd.name, bsd.getCmd("start")).Run(); err != nil { 190 return startAction + failed, err 191 } 192 193 return startAction + success, nil 194 } 195 196 // Stop the service 197 func (bsd *bsdRecord) Stop() (string, error) { 198 stopAction := "Stopping " + bsd.description + ":" 199 200 if ok, err := checkPrivileges(); !ok { 201 return stopAction + failed, err 202 } 203 204 if !bsd.isInstalled() { 205 return stopAction + failed, ErrNotInstalled 206 } 207 208 if _, ok := bsd.checkRunning(); !ok { 209 return stopAction + failed, ErrAlreadyStopped 210 } 211 212 if err := exec.Command("service", bsd.name, bsd.getCmd("stop")).Run(); err != nil { 213 return stopAction + failed, err 214 } 215 216 return stopAction + success, nil 217 } 218 219 // Status - Get service status 220 func (bsd *bsdRecord) Status() (string, error) { 221 222 if ok, err := checkPrivileges(); !ok { 223 return "", err 224 } 225 226 if !bsd.isInstalled() { 227 return statNotInstalled, ErrNotInstalled 228 } 229 230 statusAction, _ := bsd.checkRunning() 231 232 return statusAction, nil 233 } 234 235 // Run - Run service 236 func (bsd *bsdRecord) Run(e Executable) (string, error) { 237 runAction := "Running " + bsd.description + ":" 238 e.Run() 239 return runAction + " completed.", nil 240 } 241 242 // GetTemplate - gets service config template 243 func (linux *bsdRecord) GetTemplate() string { 244 return bsdConfig 245 } 246 247 // SetTemplate - sets service config template 248 func (linux *bsdRecord) SetTemplate(tplStr string) error { 249 bsdConfig = tplStr 250 return nil 251 } 252 253 var bsdConfig = `#!/bin/sh 254 # 255 # PROVIDE: {{.Name}} 256 # REQUIRE: networking syslog 257 # KEYWORD: 258 259 # Add the following lines to /etc/rc.conf to enable the {{.Name}}: 260 # 261 # {{.Name}}_enable="YES" 262 # 263 264 265 . /etc/rc.subr 266 267 name="{{.Name}}" 268 rcvar="{{.Name}}_enable" 269 command="{{.Path}}" 270 pidfile="/var/run/$name.pid" 271 272 start_cmd="/usr/sbin/daemon -p $pidfile -f $command {{.Args}}" 273 load_rc_config $name 274 run_rc_command "$1" 275 `