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  `