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  `