github.com/TeaOSLab/EdgeNode@v1.3.8/internal/utils/service_linux.go (about)

     1  //go:build linux
     2  // +build linux
     3  
     4  package utils
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
    10  	executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
    11  	"github.com/iwind/TeaGo/Tea"
    12  	"github.com/iwind/TeaGo/files"
    13  	"os"
    14  	"os/exec"
    15  	"regexp"
    16  	"time"
    17  )
    18  
    19  var systemdServiceFile = "/etc/systemd/system/edge-node.service"
    20  var initServiceFile = "/etc/init.d/" + teaconst.SystemdServiceName
    21  
    22  // Install 安装服务
    23  func (this *ServiceManager) Install(exePath string, args []string) error {
    24  	if os.Getgid() != 0 {
    25  		return errors.New("only root users can install the service")
    26  	}
    27  
    28  	systemd, err := executils.LookPath("systemctl")
    29  	if err != nil {
    30  		return this.installInitService(exePath, args)
    31  	}
    32  
    33  	return this.installSystemdService(systemd, exePath, args)
    34  }
    35  
    36  // Start 启动服务
    37  func (this *ServiceManager) Start() error {
    38  	if os.Getgid() != 0 {
    39  		return errors.New("only root users can start the service")
    40  	}
    41  
    42  	if files.NewFile(systemdServiceFile).Exists() {
    43  		systemd, err := executils.LookPath("systemctl")
    44  		if err != nil {
    45  			return err
    46  		}
    47  
    48  		return exec.Command(systemd, "start", teaconst.SystemdServiceName+".service").Start()
    49  	}
    50  	return exec.Command("service", teaconst.ProcessName, "start").Start()
    51  }
    52  
    53  // Uninstall 删除服务
    54  func (this *ServiceManager) Uninstall() error {
    55  	if os.Getgid() != 0 {
    56  		return errors.New("only root users can uninstall the service")
    57  	}
    58  
    59  	if files.NewFile(systemdServiceFile).Exists() {
    60  		systemd, err := executils.LookPath("systemctl")
    61  		if err != nil {
    62  			return err
    63  		}
    64  
    65  		// disable service
    66  		_ = executils.NewTimeoutCmd(10*time.Second, systemd, "disable", teaconst.SystemdServiceName+".service").Start()
    67  
    68  		// reload
    69  		_ = executils.NewTimeoutCmd(10*time.Second, systemd, "daemon-reload").Start()
    70  
    71  		return files.NewFile(systemdServiceFile).Delete()
    72  	}
    73  
    74  	f := files.NewFile(initServiceFile)
    75  	if f.Exists() {
    76  		return f.Delete()
    77  	}
    78  	return nil
    79  }
    80  
    81  // install init service
    82  func (this *ServiceManager) installInitService(exePath string, args []string) error {
    83  	shortName := teaconst.SystemdServiceName
    84  	scriptFile := Tea.Root + "/scripts/" + shortName
    85  	if !files.NewFile(scriptFile).Exists() {
    86  		return errors.New("'scripts/" + shortName + "' file not exists")
    87  	}
    88  
    89  	data, err := os.ReadFile(scriptFile)
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	data = regexp.MustCompile("INSTALL_DIR=.+").ReplaceAll(data, []byte("INSTALL_DIR="+Tea.Root))
    95  	err = os.WriteFile(initServiceFile, data, 0777)
    96  	if err != nil {
    97  		return err
    98  	}
    99  
   100  	chkCmd, err := executils.LookPath("chkconfig")
   101  	if err != nil {
   102  		return err
   103  	}
   104  
   105  	err = exec.Command(chkCmd, "--add", teaconst.ProcessName).Start()
   106  	if err != nil {
   107  		return err
   108  	}
   109  
   110  	return nil
   111  }
   112  
   113  // install systemd service
   114  func (this *ServiceManager) installSystemdService(systemd, exePath string, args []string) error {
   115  	var shortName = teaconst.SystemdServiceName
   116  	var longName = "GoEdge Node" // TODO 将来可以修改
   117  
   118  	var startCmd = exePath + " daemon"
   119  	bashPath, _ := executils.LookPath("bash")
   120  	if len(bashPath) > 0 {
   121  		startCmd = bashPath + " -c \"" + startCmd + "\""
   122  	}
   123  
   124  	var desc = `### BEGIN INIT INFO
   125  # Provides:          ` + shortName + `
   126  # Required-Start:    $all
   127  # Required-Stop:
   128  # Default-Start:     2 3 4 5
   129  # Default-Stop:
   130  # Short-Description: ` + longName + ` Service
   131  ### END INIT INFO
   132  
   133  [Unit]
   134  Description=` + longName + ` Service
   135  Before=shutdown.target
   136  After=network-online.target
   137  
   138  [Service]
   139  Type=simple
   140  Restart=always
   141  RestartSec=1s
   142  ExecStart=` + startCmd + `
   143  ExecStop=` + exePath + ` stop
   144  ExecReload=` + exePath + ` reload
   145  
   146  [Install]
   147  WantedBy=multi-user.target`
   148  
   149  	// write file
   150  	err := os.WriteFile(systemdServiceFile, []byte(desc), 0777)
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	// stop current systemd service if running
   156  	_ = executils.NewTimeoutCmd(10*time.Second, systemd, "stop", shortName+".service").Start()
   157  
   158  	// reload
   159  	_ = executils.NewTimeoutCmd(10*time.Second, systemd, "daemon-reload").Start()
   160  
   161  	// enable
   162  	var cmd = executils.NewTimeoutCmd(10*time.Second, systemd, "enable", shortName+".service")
   163  	cmd.WithStderr()
   164  	err = cmd.Run()
   165  	if err != nil {
   166  		return fmt.Errorf("%w: %s", err, cmd.Stderr())
   167  	}
   168  	return nil
   169  }