gitee.com/quant1x/gox@v1.21.2/daemon/daemon_linux_systemd.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  // systemDRecord - standard record (struct) for linux systemD version of daemon package
    16  type systemDRecord struct {
    17  	name         string
    18  	description  string
    19  	kind         Kind
    20  	dependencies []string
    21  }
    22  
    23  // Standard service path for systemD daemons
    24  func (linux *systemDRecord) servicePath() string {
    25  	return "/etc/systemd/system/" + linux.name + ".service"
    26  }
    27  
    28  // Is a service installed
    29  func (linux *systemDRecord) 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 *systemDRecord) checkRunning() (string, bool) {
    40  	output, err := exec.Command("systemctl", "status", linux.name+".service").Output()
    41  	if err == nil {
    42  		if matched, err := regexp.MatchString("Active: active", string(output)); err == nil && matched {
    43  			reg := regexp.MustCompile("Main 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 *systemDRecord) 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("systemDConfig").Parse(systemDConfig)
    81  	if err != nil {
    82  		return installAction + failed, err
    83  	}
    84  
    85  	if err := templ.Execute(
    86  		file,
    87  		&struct {
    88  			Name, Description, Dependencies, Path, Args string
    89  		}{
    90  			linux.name,
    91  			linux.description,
    92  			strings.Join(linux.dependencies, " "),
    93  			execPatch,
    94  			strings.Join(args, " "),
    95  		},
    96  	); err != nil {
    97  		return installAction + failed, err
    98  	}
    99  
   100  	if err := exec.Command("systemctl", "daemon-reload").Run(); err != nil {
   101  		return installAction + failed, err
   102  	}
   103  
   104  	if err := exec.Command("systemctl", "enable", linux.name+".service").Run(); err != nil {
   105  		return installAction + failed, err
   106  	}
   107  
   108  	return installAction + success, nil
   109  }
   110  
   111  // Remove the service
   112  func (linux *systemDRecord) Remove() (string, error) {
   113  	removeAction := "Removing " + linux.description + ":"
   114  
   115  	if ok, err := checkPrivileges(); !ok {
   116  		return removeAction + failed, err
   117  	}
   118  
   119  	if !linux.isInstalled() {
   120  		return removeAction + failed, ErrNotInstalled
   121  	}
   122  
   123  	if err := exec.Command("systemctl", "disable", linux.name+".service").Run(); err != nil {
   124  		return removeAction + failed, err
   125  	}
   126  
   127  	if err := os.Remove(linux.servicePath()); err != nil {
   128  		return removeAction + failed, err
   129  	}
   130  
   131  	return removeAction + success, nil
   132  }
   133  
   134  // Start the service
   135  func (linux *systemDRecord) Start() (string, error) {
   136  	startAction := "Starting " + linux.description + ":"
   137  
   138  	if ok, err := checkPrivileges(); !ok {
   139  		return startAction + failed, err
   140  	}
   141  
   142  	if !linux.isInstalled() {
   143  		return startAction + failed, ErrNotInstalled
   144  	}
   145  
   146  	if _, ok := linux.checkRunning(); ok {
   147  		return startAction + failed, ErrAlreadyRunning
   148  	}
   149  
   150  	if err := exec.Command("systemctl", "start", linux.name+".service").Run(); err != nil {
   151  		return startAction + failed, err
   152  	}
   153  
   154  	return startAction + success, nil
   155  }
   156  
   157  // Stop the service
   158  func (linux *systemDRecord) Stop() (string, error) {
   159  	stopAction := "Stopping " + linux.description + ":"
   160  
   161  	if ok, err := checkPrivileges(); !ok {
   162  		return stopAction + failed, err
   163  	}
   164  
   165  	if !linux.isInstalled() {
   166  		return stopAction + failed, ErrNotInstalled
   167  	}
   168  
   169  	if _, ok := linux.checkRunning(); !ok {
   170  		return stopAction + failed, ErrAlreadyStopped
   171  	}
   172  
   173  	if err := exec.Command("systemctl", "stop", linux.name+".service").Run(); err != nil {
   174  		return stopAction + failed, err
   175  	}
   176  
   177  	return stopAction + success, nil
   178  }
   179  
   180  // Status - Get service status
   181  func (linux *systemDRecord) Status() (string, error) {
   182  
   183  	if ok, err := checkPrivileges(); !ok {
   184  		return "", err
   185  	}
   186  
   187  	if !linux.isInstalled() {
   188  		return statNotInstalled, ErrNotInstalled
   189  	}
   190  
   191  	statusAction, _ := linux.checkRunning()
   192  
   193  	return statusAction, nil
   194  }
   195  
   196  // Run - Run service
   197  func (linux *systemDRecord) Run(e Executable) (string, error) {
   198  	runAction := "Running " + linux.description + ":"
   199  	e.Run()
   200  	return runAction + " completed.", nil
   201  }
   202  
   203  // GetTemplate - gets service config template
   204  func (linux *systemDRecord) GetTemplate() string {
   205  	return systemDConfig
   206  }
   207  
   208  // SetTemplate - sets service config template
   209  func (linux *systemDRecord) SetTemplate(tplStr string) error {
   210  	systemDConfig = tplStr
   211  	return nil
   212  }
   213  
   214  var systemDConfig = `[Unit]
   215  Description={{.Description}}
   216  Requires={{.Dependencies}}
   217  After={{.Dependencies}}
   218  
   219  [Service]
   220  PIDFile=/var/run/{{.Name}}.pid
   221  ExecStartPre=/bin/rm -f /var/run/{{.Name}}.pid
   222  ExecStart={{.Path}} {{.Args}}
   223  Restart=on-failure
   224  
   225  [Install]
   226  WantedBy=multi-user.target
   227  `