Add System-V support
This commit is contained in:
+150
-4
@@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log/syslog"
|
||||
"os"
|
||||
@@ -12,13 +13,17 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
initUpstart = initFlavor(iota)
|
||||
initSystemV = initFlavor(iota)
|
||||
initUpstart
|
||||
initSystemd
|
||||
)
|
||||
|
||||
func newService(name, displayName, description string) (Service, error) {
|
||||
flavor := initUpstart
|
||||
if _, err := os.Stat("/run/systemd/system"); err == nil {
|
||||
flavor := initSystemV
|
||||
if isUpstart() {
|
||||
flavor = initUpstart
|
||||
}
|
||||
if isSystemd() {
|
||||
flavor = initSystemd
|
||||
}
|
||||
s := &linuxService{
|
||||
@@ -37,6 +42,32 @@ func newService(name, displayName, description string) (Service, error) {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func isUpstart() bool {
|
||||
f, err := os.Open("/etc/lsb-release")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer f.Close()
|
||||
r := bufio.NewReader(f)
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
if scanner.Text() == "DISTRIB_ID=Ubuntu" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isSystemd() bool {
|
||||
if _, err := os.Stat("/run/systemd/system"); err == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type linuxService struct {
|
||||
flavor initFlavor
|
||||
name, displayName, description string
|
||||
@@ -47,6 +78,8 @@ type initFlavor uint8
|
||||
|
||||
func (f initFlavor) String() string {
|
||||
switch f {
|
||||
case initSystemV:
|
||||
return "System-V"
|
||||
case initUpstart:
|
||||
return "Upstart"
|
||||
case initSystemd:
|
||||
@@ -58,6 +91,8 @@ func (f initFlavor) String() string {
|
||||
|
||||
func (f initFlavor) ConfigPath(name string) string {
|
||||
switch f {
|
||||
case initSystemV:
|
||||
return "/etc/init.d/" + name
|
||||
case initUpstart:
|
||||
return "/etc/init/" + name + ".conf"
|
||||
case initSystemd:
|
||||
@@ -70,6 +105,8 @@ func (f initFlavor) ConfigPath(name string) string {
|
||||
func (f initFlavor) GetTemplate() *template.Template {
|
||||
var templ string
|
||||
switch f {
|
||||
case initSystemV:
|
||||
templ = systemVScript
|
||||
case initUpstart:
|
||||
templ = upstartScript
|
||||
case initSystemd:
|
||||
@@ -107,11 +144,26 @@ func (s *linuxService) Install() error {
|
||||
}
|
||||
|
||||
err = s.flavor.GetTemplate().Execute(f, to)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if s.flavor == initSystemV {
|
||||
if err = os.Chmod(confPath, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, i := range [...]string{"2", "3", "4", "5"} {
|
||||
if err = os.Symlink(confPath, "/etc/rc"+i+".d/S50"+s.name); err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
for _, i := range [...]string{"0", "1", "6"} {
|
||||
if err = os.Symlink(confPath, "/etc/rc"+i+".d/K02"+s.name); err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if s.flavor == initSystemd {
|
||||
return exec.Command("systemctl", "daemon-reload").Run()
|
||||
}
|
||||
@@ -165,6 +217,100 @@ func (s *linuxService) Info(format string, a ...interface{}) error {
|
||||
return s.logger.Info(fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
const systemVScript = `#!/bin/sh
|
||||
# For RedHat and cousins:
|
||||
# chkconfig: - 99 01
|
||||
# description: {{.Description}}
|
||||
# processname: {{.Path}}
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: {{.Path}}
|
||||
# Required-Start:
|
||||
# Required-Stop:
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: {{.Display}}
|
||||
# Description: {{.Description}}
|
||||
### END INIT INFO
|
||||
|
||||
cmd="{{.Path}}"
|
||||
|
||||
name=$(basename $0)
|
||||
pid_file="/var/run/$name.pid"
|
||||
stdout_log="/var/log/$name.log"
|
||||
stderr_log="/var/log/$name.err"
|
||||
|
||||
get_pid() {
|
||||
cat "$pid_file"
|
||||
}
|
||||
|
||||
is_running() {
|
||||
[ -f "$pid_file" ] && ps $(get_pid) > /dev/null 2>&1
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if is_running; then
|
||||
echo "Already started"
|
||||
else
|
||||
echo "Starting $name"
|
||||
$cmd >> "$stdout_log" 2>> "$stderr_log" &
|
||||
echo $! > "$pid_file"
|
||||
if ! is_running; then
|
||||
echo "Unable to start, see $stdout_log and $stderr_log"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
stop)
|
||||
if is_running; then
|
||||
echo -n "Stopping $name.."
|
||||
kill $(get_pid)
|
||||
for i in {1..10}
|
||||
do
|
||||
if ! is_running; then
|
||||
break
|
||||
fi
|
||||
echo -n "."
|
||||
sleep 1
|
||||
done
|
||||
echo
|
||||
if is_running; then
|
||||
echo "Not stopped; may still be shutting down or shutdown may have failed"
|
||||
exit 1
|
||||
else
|
||||
echo "Stopped"
|
||||
if [ -f "$pid_file" ]; then
|
||||
rm "$pid_file"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "Not running"
|
||||
fi
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
if is_running; then
|
||||
echo "Unable to stop, will not attempt to start"
|
||||
exit 1
|
||||
fi
|
||||
$0 start
|
||||
;;
|
||||
status)
|
||||
if is_running; then
|
||||
echo "Running"
|
||||
else
|
||||
echo "Stopped"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|status}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit 0`
|
||||
|
||||
const upstartScript = `# {{.Description}}
|
||||
|
||||
description "{{.Display}}"
|
||||
|
||||
Reference in New Issue
Block a user