gitee.com/quant1x/gox@v1.21.2/daemon/daemon_linux_systemv.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 "os" 9 "os/exec" 10 "regexp" 11 "strings" 12 "text/template" 13 ) 14 15 // systemVRecord - standard record (struct) for linux systemV version of daemon package 16 type systemVRecord struct { 17 name string 18 description string 19 kind Kind 20 dependencies []string 21 } 22 23 // Standard service path for systemV daemons 24 func (linux *systemVRecord) servicePath() string { 25 return "/etc/init.d/" + linux.name 26 } 27 28 // Is a service installed 29 func (linux *systemVRecord) isInstalled() bool { 30 31 if _, err := os.Stat(linux.servicePath()); err == nil { 32 return true 33 } 34 35 return false 36 } 37 38 // Check service is running 39 func (linux *systemVRecord) checkRunning() (string, bool) { 40 output, err := exec.Command("service", linux.name, "status").Output() 41 if err == nil { 42 if matched, err := regexp.MatchString(linux.name, string(output)); err == nil && matched { 43 reg := regexp.MustCompile("pid ([0-9]+)") 44 data := reg.FindStringSubmatch(string(output)) 45 if len(data) > 1 { 46 return "Service (pid " + data[1] + ") is running...", true 47 } 48 return "Service is running...", true 49 } 50 } 51 52 return "Service is stopped", false 53 } 54 55 // Install the service 56 func (linux *systemVRecord) Install(args ...string) (string, error) { 57 installAction := "Install " + linux.description + ":" 58 59 if ok, err := checkPrivileges(); !ok { 60 return installAction + failed, err 61 } 62 63 srvPath := linux.servicePath() 64 65 if linux.isInstalled() { 66 return installAction + failed, ErrAlreadyInstalled 67 } 68 69 file, err := os.Create(srvPath) 70 if err != nil { 71 return installAction + failed, err 72 } 73 defer file.Close() 74 75 execPatch, err := executablePath(linux.name) 76 if err != nil { 77 return installAction + failed, err 78 } 79 80 templ, err := template.New("systemVConfig").Parse(systemVConfig) 81 if err != nil { 82 return installAction + failed, err 83 } 84 85 if err := templ.Execute( 86 file, 87 &struct { 88 Name, Description, Path, Args string 89 }{linux.name, linux.description, execPatch, strings.Join(args, " ")}, 90 ); err != nil { 91 return installAction + failed, err 92 } 93 94 if err := os.Chmod(srvPath, 0755); err != nil { 95 return installAction + failed, err 96 } 97 98 for _, i := range [...]string{"2", "3", "4", "5"} { 99 if err := os.Symlink(srvPath, "/etc/rc"+i+".d/S87"+linux.name); err != nil { 100 continue 101 } 102 } 103 for _, i := range [...]string{"0", "1", "6"} { 104 if err := os.Symlink(srvPath, "/etc/rc"+i+".d/K17"+linux.name); err != nil { 105 continue 106 } 107 } 108 109 return installAction + success, nil 110 } 111 112 // Remove the service 113 func (linux *systemVRecord) Remove() (string, error) { 114 removeAction := "Removing " + linux.description + ":" 115 116 if ok, err := checkPrivileges(); !ok { 117 return removeAction + failed, err 118 } 119 120 if !linux.isInstalled() { 121 return removeAction + failed, ErrNotInstalled 122 } 123 124 if err := os.Remove(linux.servicePath()); err != nil { 125 return removeAction + failed, err 126 } 127 128 for _, i := range [...]string{"2", "3", "4", "5"} { 129 if err := os.Remove("/etc/rc" + i + ".d/S87" + linux.name); err != nil { 130 continue 131 } 132 } 133 for _, i := range [...]string{"0", "1", "6"} { 134 if err := os.Remove("/etc/rc" + i + ".d/K17" + linux.name); err != nil { 135 continue 136 } 137 } 138 139 return removeAction + success, nil 140 } 141 142 // Start the service 143 func (linux *systemVRecord) Start() (string, error) { 144 startAction := "Starting " + linux.description + ":" 145 146 if ok, err := checkPrivileges(); !ok { 147 return startAction + failed, err 148 } 149 150 if !linux.isInstalled() { 151 return startAction + failed, ErrNotInstalled 152 } 153 154 if _, ok := linux.checkRunning(); ok { 155 return startAction + failed, ErrAlreadyRunning 156 } 157 158 if err := exec.Command("service", linux.name, "start").Run(); err != nil { 159 return startAction + failed, err 160 } 161 162 return startAction + success, nil 163 } 164 165 // Stop the service 166 func (linux *systemVRecord) Stop() (string, error) { 167 stopAction := "Stopping " + linux.description + ":" 168 169 if ok, err := checkPrivileges(); !ok { 170 return stopAction + failed, err 171 } 172 173 if !linux.isInstalled() { 174 return stopAction + failed, ErrNotInstalled 175 } 176 177 if _, ok := linux.checkRunning(); !ok { 178 return stopAction + failed, ErrAlreadyStopped 179 } 180 181 if err := exec.Command("service", linux.name, "stop").Run(); err != nil { 182 return stopAction + failed, err 183 } 184 185 return stopAction + success, nil 186 } 187 188 // Status - Get service status 189 func (linux *systemVRecord) Status() (string, error) { 190 191 if ok, err := checkPrivileges(); !ok { 192 return "", err 193 } 194 195 if !linux.isInstalled() { 196 return statNotInstalled, ErrNotInstalled 197 } 198 199 statusAction, _ := linux.checkRunning() 200 201 return statusAction, nil 202 } 203 204 // Run - Run service 205 func (linux *systemVRecord) Run(e Executable) (string, error) { 206 runAction := "Running " + linux.description + ":" 207 e.Run() 208 return runAction + " completed.", nil 209 } 210 211 // GetTemplate - gets service config template 212 func (linux *systemVRecord) GetTemplate() string { 213 return systemVConfig 214 } 215 216 // SetTemplate - sets service config template 217 func (linux *systemVRecord) SetTemplate(tplStr string) error { 218 systemVConfig = tplStr 219 return nil 220 } 221 222 var systemVConfig = `#! /bin/sh 223 # 224 # /etc/rc.d/init.d/{{.Name}} 225 # 226 # Starts {{.Name}} as a daemon 227 # 228 # chkconfig: 2345 87 17 229 # description: Starts and stops a single {{.Name}} instance on this system 230 231 ### BEGIN INIT INFO 232 # Provides: {{.Name}} 233 # Required-Start: $network $named 234 # Required-Stop: $network $named 235 # Default-Start: 2 3 4 5 236 # Default-Stop: 0 1 6 237 # Short-Description: This service manages the {{.Description}}. 238 # Description: {{.Description}} 239 ### END INIT INFO 240 241 # 242 # Source function library. 243 # 244 if [ -f /etc/rc.d/init.d/functions ]; then 245 . /etc/rc.d/init.d/functions 246 fi 247 248 exec="{{.Path}}" 249 servname="{{.Description}}" 250 251 proc="{{.Name}}" 252 pidfile="/var/run/$proc.pid" 253 lockfile="/var/lock/subsys/$proc" 254 stdoutlog="/var/log/$proc.log" 255 stderrlog="/var/log/$proc.err" 256 257 [ -d $(dirname $lockfile) ] || mkdir -p $(dirname $lockfile) 258 259 [ -e /etc/sysconfig/$proc ] && . /etc/sysconfig/$proc 260 261 start() { 262 [ -x $exec ] || exit 5 263 264 if [ -f $pidfile ]; then 265 if ! [ -d "/proc/$(cat $pidfile)" ]; then 266 rm $pidfile 267 if [ -f $lockfile ]; then 268 rm $lockfile 269 fi 270 fi 271 fi 272 273 if ! [ -f $pidfile ]; then 274 printf "Starting $servname:\t" 275 echo "$(date)" >> $stdoutlog 276 $exec {{.Args}} >> $stdoutlog 2>> $stderrlog & 277 echo $! > $pidfile 278 touch $lockfile 279 success 280 echo 281 else 282 # failure 283 echo 284 printf "$pidfile still exists...\n" 285 exit 7 286 fi 287 } 288 289 stop() { 290 echo -n $"Stopping $servname: " 291 killproc -p $pidfile $proc 292 retval=$? 293 echo 294 [ $retval -eq 0 ] && rm -f $lockfile 295 return $retval 296 } 297 298 restart() { 299 stop 300 start 301 } 302 303 rh_status() { 304 status -p $pidfile $proc 305 } 306 307 rh_status_q() { 308 rh_status >/dev/null 2>&1 309 } 310 311 case "$1" in 312 start) 313 rh_status_q && exit 0 314 $1 315 ;; 316 stop) 317 rh_status_q || exit 0 318 $1 319 ;; 320 restart) 321 $1 322 ;; 323 status) 324 rh_status 325 ;; 326 *) 327 echo $"Usage: $0 {start|stop|status|restart}" 328 exit 2 329 esac 330 331 exit $? 332 `