github.com/TeaOSLab/EdgeNode@v1.3.8/internal/nodes/system_services.go (about)

     1  package nodes
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
     8  	teaconst "github.com/TeaOSLab/EdgeNode/internal/const"
     9  	"github.com/TeaOSLab/EdgeNode/internal/events"
    10  	"github.com/TeaOSLab/EdgeNode/internal/goman"
    11  	"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
    12  	"github.com/TeaOSLab/EdgeNode/internal/utils"
    13  	executils "github.com/TeaOSLab/EdgeNode/internal/utils/exec"
    14  	"github.com/iwind/TeaGo/maps"
    15  	"os"
    16  	"runtime"
    17  	"time"
    18  )
    19  
    20  func init() {
    21  	if !teaconst.IsMain {
    22  		return
    23  	}
    24  
    25  	var manager = NewSystemServiceManager()
    26  	events.On(events.EventReload, func() {
    27  		goman.New(func() {
    28  			err := manager.Setup()
    29  			if err != nil {
    30  				remotelogs.Error("SYSTEM_SERVICE", "setup system services failed: "+err.Error())
    31  			}
    32  		})
    33  	})
    34  }
    35  
    36  // SystemServiceManager 系统服务管理
    37  type SystemServiceManager struct {
    38  	lastIsOn int // -1, 0, 1
    39  }
    40  
    41  func NewSystemServiceManager() *SystemServiceManager {
    42  	return &SystemServiceManager{}
    43  }
    44  
    45  func (this *SystemServiceManager) Setup() error {
    46  	if sharedNodeConfig == nil || !sharedNodeConfig.IsOn {
    47  		return nil
    48  	}
    49  
    50  	if len(sharedNodeConfig.SystemServices) == 0 {
    51  		return nil
    52  	}
    53  
    54  	systemdParams, ok := sharedNodeConfig.SystemServices[nodeconfigs.SystemServiceTypeSystemd]
    55  	if ok {
    56  		err := this.setupSystemd(systemdParams)
    57  		if err != nil {
    58  			return err
    59  		}
    60  	}
    61  
    62  	return nil
    63  }
    64  
    65  func (this *SystemServiceManager) setupSystemd(params maps.Map) error {
    66  	// 只有在Linux下运行
    67  	if runtime.GOOS != "linux" {
    68  		return nil
    69  	}
    70  
    71  	if params == nil {
    72  		params = maps.Map{}
    73  	}
    74  	data, err := json.Marshal(params)
    75  	if err != nil {
    76  		return err
    77  	}
    78  
    79  	var config = &nodeconfigs.SystemdServiceConfig{}
    80  	err = json.Unmarshal(data, config)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	// 检查当前的service
    86  	systemctl, err := executils.LookPath("systemctl")
    87  	if err != nil {
    88  		return err
    89  	}
    90  	if len(systemctl) == 0 {
    91  		return errors.New("can not find 'systemctl' on the system")
    92  	}
    93  
    94  	// 记录上次状态
    95  	var isOnInt int
    96  	if config.IsOn {
    97  		isOnInt = 1
    98  	} else {
    99  		isOnInt = 0
   100  	}
   101  
   102  	if this.lastIsOn == isOnInt {
   103  		return nil
   104  	}
   105  	defer func() {
   106  		this.lastIsOn = isOnInt
   107  	}()
   108  
   109  	var shortName = teaconst.SystemdServiceName
   110  	var cmd = executils.NewTimeoutCmd(10*time.Second, systemctl, "is-enabled", shortName)
   111  	cmd.WithStdout()
   112  	err = cmd.Run()
   113  	var hasInstalled = err == nil
   114  	if config.IsOn {
   115  		exe, err := os.Executable()
   116  		if err != nil {
   117  			return err
   118  		}
   119  
   120  		// 检查文件路径是否变化
   121  		if hasInstalled && cmd.Stdout() == "enabled" {
   122  			data, err := os.ReadFile("/etc/systemd/system/" + teaconst.SystemdServiceName + ".service")
   123  			if err == nil && bytes.Index(data, []byte(exe)) > 0 {
   124  				return nil
   125  			}
   126  		}
   127  
   128  		// 安装服务
   129  		var manager = utils.NewServiceManager(shortName, teaconst.ProductName)
   130  		err = manager.Install(exe, []string{})
   131  		if err != nil {
   132  			return err
   133  		}
   134  
   135  		// 启动服务
   136  		goman.New(func() {
   137  			time.Sleep(5 * time.Second)
   138  			_ = executils.NewTimeoutCmd(30*time.Second, systemctl, "start", teaconst.SystemdServiceName).Start()
   139  		})
   140  	} else {
   141  		if hasInstalled {
   142  			var manager = utils.NewServiceManager(shortName, teaconst.ProductName)
   143  			err = manager.Uninstall()
   144  			if err != nil {
   145  				return err
   146  			}
   147  		}
   148  	}
   149  
   150  	return nil
   151  }