Skip to content

Run go programs as a service on major platforms.

License

Notifications You must be signed in to change notification settings

morfien101/service

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

service GoDoc

service will install / un-install, start / stop, and run a program as a service (daemon). Currently supports Windows XP+, Linux/(systemd | Upstart | SysV), and OSX/Launchd.

Windows controls services by setting up callbacks that is non-trivial. This is very different then other systems. This package provides the same API despite the substantial differences. It also can be used to detect how a program is called, from an interactive terminal or from a service manager.

Caveats

  • Dependencies field is not implemented for Linux systems and Launchd.
  • OS X when running as a UserService Interactive will not be accurate.

Example service

package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/morfien101/service"
)

var (
	logger  service.Logger
	version = "0.0.1"

	svcFlag      = flag.String("service", "", "Control the system service.")
	versionCheck = flag.Bool("v", false, "Outputs the version of the program.")
	helpFlag     = flag.Bool("h", false, "Shows the help menu")
)

func main() {
	digestFlags()

	svcConfig := &service.Config{
		Name:        "test_restarter",
		DisplayName: "Test Restarter",
		Description: "Service that just waits to be restarted.",
	}

	prg := &program{}

	serviceController, err := service.New(prg, svcConfig)
	if err != nil {
		log.Fatal(err)
	}

	// Create a channel to house the errors from the service.
	// These are then printed out on the go func below.
	errsChan := make(chan error, 5)
	logger, err = serviceController.Logger(errsChan)
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		for {
			err := <-errsChan
			if err != nil {
				log.Print(err)
			}
		}
	}()

	// Look for the --service flag and do what we need to here.
	if len(*svcFlag) != 0 {
		err := service.Control(serviceController, *svcFlag)
		if err != nil {
			log.Printf("Valid actions: %q\n", service.ControlAction)
			log.Fatal(err)
		}
		return
	}

	// Run() will call prg.Start() and then wait.
	// Stop() is called when a signal to stop is received.
	// Only if Start sends an error or Stop finishes will Run return.
	err = serviceController.Run()
	if err != nil {
		logger.Error(err)
	}
}

func digestFlags() {
	// Parse the flags to get the state we need to run in.
	flag.Parse()

	if *versionCheck {
		fmt.Println(version)
		os.Exit(0)
	}

	if *helpFlag {
		flag.PrintDefaults()
		os.Exit(0)
	}
}

type program struct {
	exit    chan bool
	finshed chan bool
}

func (p *program) Start(s service.Service) error {
	// Errors would relate to looking for config files.
	// To be added later.

	// This channel is used in the run section to block.
	p.exit = make(chan bool, 1)
	p.finshed = make(chan bool, 1)

	// Start the service in a async go routine
	go p.run()

	// return any errors.
	return nil
}

func (p *program) Stop(s service.Service) error {
	// This section is to shutdown the app gracefully.
	// return any errors relating to the above.
	// Send your shutdown signals to any other go routines or work flows from here.

	// This channel is used in the running section to block.
	p.exit <- true
	close(p.exit)

	// Wait till everything is shutdown
	<-p.finshed

	logger.Info("Example service is Stopping.")
	return nil
}

func (p *program) run() error {
	// This section is where your work happens.
	// In this case we just log some messages, but really this is where you would start your work flows
	// go routines, etc...
	defer func() {
		logger.Info("Example service got a signal to stop.")
	}()

	ticker := time.NewTicker(time.Second * 5)

	logger.Info("Example service is Started and waiting.")

	for {
		select {
		case <-p.exit:
			ticker.Stop()
			p.finshed <- true
			return nil
		case <-ticker.C:
			logger.Infof("Example service periodic message.")
		}
	}
}

About

Run go programs as a service on major platforms.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 98.1%
  • Makefile 1.1%
  • Other 0.8%