github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zutil/daemon/daemon_freebsd.go (about)

     1  package daemon
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  	"text/template"
     9  )
    10  
    11  type (
    12  	freebsdRcdService struct {
    13  		i Iface
    14  		*Config
    15  		userService bool
    16  	}
    17  	freebsdSystem struct{}
    18  )
    19  
    20  const version = "freebsd-rcd"
    21  
    22  var interactive = false
    23  
    24  func init() {
    25  	var err error
    26  	chooseSystem(freebsdSystem{})
    27  	interactive, err = isInteractive()
    28  	if err != nil {
    29  		panic(err)
    30  	}
    31  }
    32  
    33  func (freebsdSystem) String() string {
    34  	return version
    35  }
    36  
    37  func (freebsdSystem) Detect() bool {
    38  	return true
    39  }
    40  
    41  func (freebsdSystem) Interactive() bool {
    42  	return interactive
    43  }
    44  
    45  func (freebsdSystem) New(i Iface, c *Config) (ServiceIface, error) {
    46  	userService := optionUserServiceDefault
    47  	if s, ok := c.Options[optionUserService]; ok {
    48  		userService, _ = s.(bool)
    49  	}
    50  
    51  	if c.Context == nil {
    52  		c.Context = context.Background()
    53  	}
    54  
    55  	s := &freebsdRcdService{
    56  		i:           i,
    57  		Config:      c,
    58  		userService: userService,
    59  	}
    60  	return s, nil
    61  }
    62  
    63  func isInteractive() (bool, error) {
    64  	return os.Getppid() != 1, nil
    65  }
    66  
    67  func (s *freebsdRcdService) Status() string {
    68  	return "Unknown"
    69  }
    70  
    71  func (s *freebsdRcdService) String() string {
    72  	if len(s.DisplayName) > 0 {
    73  		return s.DisplayName
    74  	}
    75  	return s.Name
    76  }
    77  
    78  func (s *freebsdRcdService) getServiceFilePath() (string, error) {
    79  
    80  	return "/etc/rc.d/" + s.Name, nil
    81  }
    82  
    83  func (s *freebsdRcdService) Install() error {
    84  	confPath, err := s.getServiceFilePath()
    85  	if err != nil {
    86  		return err
    87  	}
    88  	_, err = os.Stat(confPath)
    89  	if err == nil {
    90  		return fmt.Errorf("init already exists: %s", confPath)
    91  	}
    92  
    93  	if s.userService {
    94  		//  ~/Library/LaunchAgents exists.
    95  		err = os.MkdirAll(filepath.Dir(confPath), 0700)
    96  		if err != nil {
    97  			return err
    98  		}
    99  	}
   100  
   101  	f, err := os.Create(confPath)
   102  	if err != nil {
   103  		return err
   104  	}
   105  	defer f.Close()
   106  
   107  	keepAlive := optionKeepAliveDefault
   108  	if v, ok := s.Options[optionKeepAlive]; ok {
   109  		keepAlive, _ = v.(bool)
   110  	}
   111  	load := isServiceRestart(s.Config)
   112  	sessionCreate := optionSessionCreateDefault
   113  	if v, ok := s.Options[optionSessionCreate]; ok {
   114  		sessionCreate, _ = v.(bool)
   115  	}
   116  
   117  	path := s.execPath()
   118  	to := &struct {
   119  		*Config
   120  		Path string
   121  
   122  		KeepAlive, RunAtLoad bool
   123  		SessionCreate        bool
   124  	}{
   125  		Config:        s.Config,
   126  		Path:          path,
   127  		KeepAlive:     keepAlive,
   128  		RunAtLoad:     load,
   129  		SessionCreate: sessionCreate,
   130  	}
   131  
   132  	functions := template.FuncMap{
   133  		"bool": func(v bool) string {
   134  			if v {
   135  				return "true"
   136  			}
   137  			return "false"
   138  		},
   139  	}
   140  
   141  	rcdScript := ""
   142  	if s.Name == "opsramp-agent" {
   143  		rcdScript = rcdScriptOpsrampAgent
   144  		file, err := os.OpenFile("/etc/rc.conf", os.O_WRONLY|os.O_APPEND, 0644)
   145  		if err != nil {
   146  			return err
   147  		}
   148  		defer file.Close()
   149  		data := "opsramp_agent_enable=" + `"` + "YES" + `"`
   150  		_, _ = fmt.Fprintln(file, data)
   151  
   152  	} else if s.Name == "opsramp-shield" {
   153  		rcdScript = rcdScriptOpsrampShield
   154  		file, err := os.OpenFile("/etc/rc.conf", os.O_WRONLY|os.O_APPEND, 0644)
   155  		if err != nil {
   156  			return err
   157  		}
   158  		defer file.Close()
   159  		data := "opsramp_shield_enable=" + `"` + "YES" + `"`
   160  		_, _ = fmt.Fprintln(file, data)
   161  
   162  	} else {
   163  		rcdScript = rcdScriptAgentUninstall
   164  		file, err := os.OpenFile("/etc/rc.conf", os.O_WRONLY|os.O_APPEND, 0644)
   165  		if err != nil {
   166  			fmt.Printf("failed opening file: %s\n", err)
   167  		}
   168  		defer file.Close()
   169  		data := "agent_uninstall_enable=" + `"` + "YES" + `"`
   170  		_, _ = fmt.Fprintln(file, data)
   171  	}
   172  
   173  	t := template.Must(template.New("rcdScript").Funcs(functions).Parse(rcdScript))
   174  	errExecute := t.Execute(f, to)
   175  
   176  	serviceName := "/etc/rc.d/" + s.Name
   177  	err = os.Chmod(serviceName, 755)
   178  	if err != nil {
   179  		return err
   180  	}
   181  
   182  	return errExecute
   183  }
   184  
   185  func (s *freebsdRcdService) Uninstall() error {
   186  	_ = s.Stop()
   187  	if s.Name == "opsramp-agent" {
   188  		_ = run("sed", "-i", "-e", "'/opsramp_agent_enable/d'", "/etc/rc.conf")
   189  	} else if s.Name == "opsramp-shield" {
   190  		_ = run("sed", "-i", "-e", "'/opsramp_shield_enable/d'", "/etc/rc.conf")
   191  	} else {
   192  		_ = run("sed", "-i", "-e", "'/agent_uninstall_enable/d'", "/etc/rc.conf")
   193  	}
   194  	confPath, err := s.getServiceFilePath()
   195  	if err != nil {
   196  		return err
   197  	}
   198  	return os.Remove(confPath)
   199  }
   200  
   201  func (s *freebsdRcdService) Start() error {
   202  	return run("service", s.Name, "start")
   203  }
   204  func (s *freebsdRcdService) Stop() error {
   205  	return run("service", s.Name, "stop")
   206  
   207  }
   208  func (s *freebsdRcdService) Restart() error {
   209  	return run("service", s.Name, "restart")
   210  
   211  }
   212  
   213  func (s *freebsdRcdService) Run() error {
   214  	var err error
   215  
   216  	err = s.i.Start(s)
   217  	if err != nil {
   218  		return err
   219  	}
   220  	runWait := func() {
   221  		select {
   222  		case <-SingleKillSignal():
   223  		case <-s.Config.Context.Done():
   224  		}
   225  	}
   226  	if v, ok := s.Options[optionRunWait]; ok {
   227  		runWait, _ = v.(func())
   228  	}
   229  	runWait()
   230  	return s.i.Stop(s)
   231  }
   232  
   233  const rcdScriptOpsrampAgent = `. /etc/rc.subr
   234  
   235  name="opsramp_agent"
   236  rcvar="opsramp_agent_enable"
   237  command="/opt/opsramp/agent/opsramp-agent service"
   238  pidfile="/var/run/${name}.pid"
   239  
   240  start_cmd="test_start"
   241  stop_cmd="test_stop"
   242  status_cmd="test_status"
   243  
   244  test_start() {
   245          /usr/sbin/daemon -p ${pidfile} ${command}
   246  }
   247  
   248  test_status() {
   249          if [ -e ${pidfile} ]; then
   250                  echo ${name} is running...
   251          else
   252                  echo ${name} is not running.
   253          fi
   254  }
   255  
   256  test_stop() {
   257          if [ -e ${pidfile} ]; then
   258  ` +
   259  	" kill `cat ${pidfile}`; " +
   260  	`
   261          else
   262                  echo ${name} is not running?
   263          fi
   264  }
   265  
   266  load_rc_config $name
   267  run_rc_command "$1"
   268  `
   269  
   270  const rcdScriptOpsrampShield = `. /etc/rc.subr
   271  
   272  name="opsramp_shield"
   273  rcvar="opsramp_shield_enable"
   274  command="/opt/opsramp/agent/bin/opsramp-shield service"
   275  pidfile="/var/run/${name}.pid"
   276  
   277  start_cmd="test_start"
   278  stop_cmd="test_stop"
   279  status_cmd="test_status"
   280  
   281  test_start() {
   282          /usr/sbin/daemon -p ${pidfile} ${command}
   283  }
   284  
   285  test_status() {
   286          if [ -e ${pidfile} ]; then
   287                  echo ${name} is running...
   288          else
   289                  echo ${name} is not running.
   290          fi
   291  }
   292  
   293  test_stop() {
   294          if [ -e ${pidfile} ]; then
   295  ` +
   296  	" kill `cat ${pidfile}`; " +
   297  	`
   298          else
   299                  echo ${name} is not running?
   300          fi
   301  }
   302  
   303  load_rc_config $name
   304  run_rc_command "$1"
   305  `
   306  const rcdScriptAgentUninstall = `. /etc/rc.subr
   307  
   308  name="agent_uninstall"
   309  rcvar="agent_uninstall_enable"
   310  command="/opt/opsramp/agent/bin/uninstall"
   311  pidfile="/var/run/${name}.pid"
   312  
   313  start_cmd="test_start"
   314  stop_cmd="test_stop"
   315  status_cmd="test_status"
   316  
   317  test_start() {
   318          /usr/sbin/daemon -p ${pidfile} ${command}
   319  }
   320  
   321  test_status() {
   322          if [ -e ${pidfile} ]; then
   323                  echo ${name} is running...
   324          else
   325                  echo ${name} is not running.
   326          fi
   327  }
   328  
   329  test_stop() {
   330          if [ -e ${pidfile} ]; then
   331  ` +
   332  	" kill `cat ${pidfile}`; " +
   333  	`
   334          else
   335                  echo ${name} is not running?
   336          fi
   337  }
   338  
   339  load_rc_config $name
   340  run_rc_command "$1"
   341  `