Add systemd support
This commit is contained in:
+94
-25
@@ -1,22 +1,34 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bitbucket.org/kardianos/osext"
|
||||
"fmt"
|
||||
"log/syslog"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"text/template"
|
||||
|
||||
"bitbucket.org/kardianos/osext"
|
||||
)
|
||||
|
||||
func newService(name, displayName, description string) (s *linuxUpstartService, err error) {
|
||||
s = &linuxUpstartService{
|
||||
const (
|
||||
initUpstart = initFlavor(iota)
|
||||
initSystemd
|
||||
)
|
||||
|
||||
func newService(name, displayName, description string) (Service, error) {
|
||||
flavor := initUpstart
|
||||
if _, err := os.Stat("/run/systemd/system"); err == nil {
|
||||
flavor = initSystemd
|
||||
}
|
||||
s := &linuxService{
|
||||
flavor: flavor,
|
||||
name: name,
|
||||
displayName: displayName,
|
||||
description: description,
|
||||
}
|
||||
|
||||
var err error
|
||||
s.logger, err = syslog.New(syslog.LOG_INFO, name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -25,13 +37,49 @@ func newService(name, displayName, description string) (s *linuxUpstartService,
|
||||
return s, nil
|
||||
}
|
||||
|
||||
type linuxUpstartService struct {
|
||||
type linuxService struct {
|
||||
flavor initFlavor
|
||||
name, displayName, description string
|
||||
logger *syslog.Writer
|
||||
}
|
||||
|
||||
func (s *linuxUpstartService) Install() error {
|
||||
var confPath = "/etc/init/" + s.name + ".conf"
|
||||
type initFlavor uint8
|
||||
|
||||
func (f initFlavor) String() string {
|
||||
switch f {
|
||||
case initUpstart:
|
||||
return "Upstart"
|
||||
case initSystemd:
|
||||
return "systemd"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (f initFlavor) ConfigPath(name string) string {
|
||||
switch f {
|
||||
case initUpstart:
|
||||
return "/etc/init/" + name + ".conf"
|
||||
case initSystemd:
|
||||
return "/etc/systemd/system/" + name + ".service"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (f initFlavor) GetTemplate() *template.Template {
|
||||
var templ string
|
||||
switch f {
|
||||
case initUpstart:
|
||||
templ = upstartScript
|
||||
case initSystemd:
|
||||
templ = systemdScript
|
||||
}
|
||||
return template.Must(template.New(f.String() + "Script").Parse(templ))
|
||||
}
|
||||
|
||||
func (s *linuxService) Install() error {
|
||||
confPath := s.flavor.ConfigPath(s.name)
|
||||
_, err := os.Stat(confPath)
|
||||
if err == nil {
|
||||
return fmt.Errorf("Init already exists: %s", confPath)
|
||||
@@ -58,58 +106,66 @@ func (s *linuxUpstartService) Install() error {
|
||||
path,
|
||||
}
|
||||
|
||||
t := template.Must(template.New("upstartScript").Parse(upstartScript))
|
||||
err = t.Execute(f, to)
|
||||
err = s.flavor.GetTemplate().Execute(f, to)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if s.flavor == initSystemd {
|
||||
return exec.Command("systemctl", "daemon-reload").Run()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *linuxUpstartService) Remove() error {
|
||||
return os.Remove("/etc/init/" + s.name + ".conf")
|
||||
func (s *linuxService) Remove() error {
|
||||
if s.flavor == initSystemd {
|
||||
exec.Command("systemctl", "disable", s.name+".service").Run()
|
||||
}
|
||||
if err := os.Remove(s.flavor.ConfigPath(s.name)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *linuxUpstartService) Run(onStart, onStop func() error) error {
|
||||
var err error
|
||||
|
||||
func (s *linuxService) Run(onStart, onStop func() error) (err error) {
|
||||
err = onStart()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
err = onStop()
|
||||
}()
|
||||
|
||||
var sigChan = make(chan os.Signal, 3)
|
||||
sigChan := make(chan os.Signal, 3)
|
||||
|
||||
signal.Notify(sigChan, os.Interrupt, os.Kill)
|
||||
|
||||
<-sigChan
|
||||
|
||||
return onStop()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *linuxUpstartService) Start() error {
|
||||
cmd := exec.Command("start", s.name)
|
||||
return cmd.Run()
|
||||
func (s *linuxService) Start() error {
|
||||
return exec.Command("service", s.name, "start").Run()
|
||||
}
|
||||
|
||||
func (s *linuxUpstartService) Stop() error {
|
||||
cmd := exec.Command("stop", s.name)
|
||||
return cmd.Run()
|
||||
func (s *linuxService) Stop() error {
|
||||
return exec.Command("service", s.name, "stop").Run()
|
||||
}
|
||||
|
||||
func (s *linuxUpstartService) Error(format string, a ...interface{}) error {
|
||||
func (s *linuxService) Error(format string, a ...interface{}) error {
|
||||
return s.logger.Err(fmt.Sprintf(format, a...))
|
||||
}
|
||||
func (s *linuxUpstartService) Warning(format string, a ...interface{}) error {
|
||||
func (s *linuxService) Warning(format string, a ...interface{}) error {
|
||||
return s.logger.Warning(fmt.Sprintf(format, a...))
|
||||
}
|
||||
func (s *linuxUpstartService) Info(format string, a ...interface{}) error {
|
||||
func (s *linuxService) Info(format string, a ...interface{}) error {
|
||||
return s.logger.Info(fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
var upstartScript = `# {{.Description}}
|
||||
const upstartScript = `# {{.Description}}
|
||||
|
||||
description "{{.Display}}"
|
||||
|
||||
@@ -133,3 +189,16 @@ end script
|
||||
# Start
|
||||
exec {{.Path}}
|
||||
`
|
||||
|
||||
const systemdScript = `[Unit]
|
||||
Description={{.Description}}
|
||||
ConditionFileIsExecutable={{.Path}}
|
||||
|
||||
[Service]
|
||||
StartLimitInterval=5
|
||||
StartLimitBurst=10
|
||||
ExecStart={{.Path}}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
`
|
||||
|
||||
Reference in New Issue
Block a user