gitee.com/sy_183/go-common@v1.0.5-0.20231205030221-958cfe129b47/system/service/service_systemd_linux.go (about)

     1  package svc
     2  
     3  import (
     4  	"gitee.com/sy_183/go-common/lifecycle"
     5  	"os"
     6  	"os/signal"
     7  )
     8  
     9  var isLinuxSystemdService = false
    10  
    11  func init() {
    12  	if _, err := os.Stat("/run/systemd/system"); err == nil {
    13  		isLinuxSystemdService = true
    14  	}
    15  }
    16  
    17  type linuxSystemdService struct {
    18  	app      lifecycle.Lifecycle
    19  	exitCode int
    20  
    21  	systemdNotify bool
    22  
    23  	notifySignals  []os.Signal
    24  	signalCallback func(sig os.Signal) (exit bool)
    25  	exitCodeGetter func(err *Error) int
    26  }
    27  
    28  func New(name string, app lifecycle.Lifecycle, options ...Option) Service {
    29  	lss := &linuxSystemdService{
    30  		app:            app,
    31  		systemdNotify:  isLinuxSystemdService,
    32  		notifySignals:  DefaultNotifySignals[:],
    33  		signalCallback: DefaultSignalCallback,
    34  		exitCodeGetter: DefaultExitCodeGetter,
    35  	}
    36  	for _, option := range options {
    37  		option.apply(lss)
    38  	}
    39  	return lss
    40  }
    41  
    42  func (lss *linuxSystemdService) setSignalNotify(callback func(sig os.Signal) (exit bool), sig ...os.Signal) {
    43  	lss.signalCallback = callback
    44  	lss.notifySignals = sig
    45  }
    46  
    47  func (lss *linuxSystemdService) setExitCodeGetter(exitCodeGetter func(err *Error) int) {
    48  	lss.exitCodeGetter = exitCodeGetter
    49  }
    50  
    51  func (lss *linuxSystemdService) Run() int {
    52  	go lss.app.Run()
    53  
    54  	sigChan := make(chan os.Signal)
    55  	signal.Notify(sigChan, lss.notifySignals...)
    56  
    57  	startedWaiter := lss.app.StartedWaiter()
    58  	closedWaiter := make(lifecycle.ChanFuture[error], 1)
    59  	for {
    60  		select {
    61  		case sig := <-sigChan:
    62  			if lss.signalCallback(sig) {
    63  				if lss.systemdNotify {
    64  					SystemdNotify("STOPPING=1")
    65  				}
    66  				lss.app.Close(nil)
    67  			}
    68  		case err := <-startedWaiter:
    69  			if err != nil {
    70  				return lss.exitCodeGetter(&Error{Type: StartError, Err: err})
    71  			}
    72  			lss.app.AddClosedFuture(closedWaiter)
    73  			if lss.systemdNotify {
    74  				SystemdNotify("READY=1")
    75  			}
    76  		case err := <-closedWaiter:
    77  			if err != nil {
    78  				return lss.exitCodeGetter(&Error{Type: ExitError, Err: err})
    79  			}
    80  			return 0
    81  		}
    82  	}
    83  }