github地址:
https://github.com/judwhite/go-svc
svc封装了Service接口用于程序的初始化、启动以及退出
type Service interface { // Init is called before the program/service is started and after it's // determined if the program is running as a Windows Service. Init(Environment) error // Start is called after Init. This method must be non-blocking. Start() error // Stop is called in response to syscall.SIGINT, syscall.SIGTERM, or when a // Windows Service is stopped. Stop() error}
通过调用Run方法,监听系统的信号量,在收到退出信号的时候执行Stop()方法
// Run runs your Service.//// Run will block until one of the signals specified in sig is received.// If sig is empty syscall.SIGINT and syscall.SIGTERM are used by default.func Run(service Service, sig ...os.Signal) error { env := environment{} if err := service.Init(env); err != nil { return err } if err := service.Start(); err != nil { return err } if len(sig) == 0 { sig = []os.Signal{syscall.SIGINT, syscall.SIGTERM} } signalChan := make(chan os.Signal, 1) signalNotify(signalChan, sig...) <-signalChan return service.Stop()}
针对Windows系统做特殊处理
// Run runs an implementation of the Service interface.//// Run will block until the Windows Service is stopped or Ctrl+C is pressed if// running from the console.//// Stopping the Windows Service and Ctrl+C will call the Service's Stop method to// initiate a graceful shutdown.//// Note that WM_CLOSE is not handled (end task) and the Service's Stop method will// not be called.//// The sig parameter is to keep parity with the non-Windows API. Only syscall.SIGINT// (Ctrl+C) can be handled on Windows. Nevertheless, you can override the default// signals which are handled by specifying sig.func Run(service Service, sig ...os.Signal) error { var err error interactive, err := svcIsAnInteractiveSession() if err != nil { return err } if len(sig) == 0 { sig = []os.Signal{syscall.SIGINT} } ws := &windowsService{ i: service, isInteractive: interactive, signals: sig, } if ws.IsWindowsService() { // the working directory for a Windows Service is C:\Windows\System32 // this is almost certainly not what the user wants. dir := filepath.Dir(os.Args[0]) if err = os.Chdir(dir); err != nil { return err } } if err = service.Init(ws); err != nil { return err } return ws.run()}