Add System-V support
This commit is contained in:
+150
-4
@@ -1,6 +1,7 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/syslog"
|
"log/syslog"
|
||||||
"os"
|
"os"
|
||||||
@@ -12,13 +13,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
initUpstart = initFlavor(iota)
|
initSystemV = initFlavor(iota)
|
||||||
|
initUpstart
|
||||||
initSystemd
|
initSystemd
|
||||||
)
|
)
|
||||||
|
|
||||||
func newService(name, displayName, description string) (Service, error) {
|
func newService(name, displayName, description string) (Service, error) {
|
||||||
flavor := initUpstart
|
flavor := initSystemV
|
||||||
if _, err := os.Stat("/run/systemd/system"); err == nil {
|
if isUpstart() {
|
||||||
|
flavor = initUpstart
|
||||||
|
}
|
||||||
|
if isSystemd() {
|
||||||
flavor = initSystemd
|
flavor = initSystemd
|
||||||
}
|
}
|
||||||
s := &linuxService{
|
s := &linuxService{
|
||||||
@@ -37,6 +42,32 @@ func newService(name, displayName, description string) (Service, error) {
|
|||||||
return s, nil
|
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 {
|
type linuxService struct {
|
||||||
flavor initFlavor
|
flavor initFlavor
|
||||||
name, displayName, description string
|
name, displayName, description string
|
||||||
@@ -47,6 +78,8 @@ type initFlavor uint8
|
|||||||
|
|
||||||
func (f initFlavor) String() string {
|
func (f initFlavor) String() string {
|
||||||
switch f {
|
switch f {
|
||||||
|
case initSystemV:
|
||||||
|
return "System-V"
|
||||||
case initUpstart:
|
case initUpstart:
|
||||||
return "Upstart"
|
return "Upstart"
|
||||||
case initSystemd:
|
case initSystemd:
|
||||||
@@ -58,6 +91,8 @@ func (f initFlavor) String() string {
|
|||||||
|
|
||||||
func (f initFlavor) ConfigPath(name string) string {
|
func (f initFlavor) ConfigPath(name string) string {
|
||||||
switch f {
|
switch f {
|
||||||
|
case initSystemV:
|
||||||
|
return "/etc/init.d/" + name
|
||||||
case initUpstart:
|
case initUpstart:
|
||||||
return "/etc/init/" + name + ".conf"
|
return "/etc/init/" + name + ".conf"
|
||||||
case initSystemd:
|
case initSystemd:
|
||||||
@@ -70,6 +105,8 @@ func (f initFlavor) ConfigPath(name string) string {
|
|||||||
func (f initFlavor) GetTemplate() *template.Template {
|
func (f initFlavor) GetTemplate() *template.Template {
|
||||||
var templ string
|
var templ string
|
||||||
switch f {
|
switch f {
|
||||||
|
case initSystemV:
|
||||||
|
templ = systemVScript
|
||||||
case initUpstart:
|
case initUpstart:
|
||||||
templ = upstartScript
|
templ = upstartScript
|
||||||
case initSystemd:
|
case initSystemd:
|
||||||
@@ -107,11 +144,26 @@ func (s *linuxService) Install() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = s.flavor.GetTemplate().Execute(f, to)
|
err = s.flavor.GetTemplate().Execute(f, to)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
if s.flavor == initSystemd {
|
||||||
return exec.Command("systemctl", "daemon-reload").Run()
|
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...))
|
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}}
|
const upstartScript = `# {{.Description}}
|
||||||
|
|
||||||
description "{{.Display}}"
|
description "{{.Display}}"
|
||||||
|
|||||||
Reference in New Issue
Block a user