109 lines
2.3 KiB
Go
109 lines
2.3 KiB
Go
// Copyright 2015 Daniel Theophanes.
|
|
// Use of this source code is governed by a zlib-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package service
|
|
|
|
import (
|
|
"bufio"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
var cgroupFile = "/proc/1/cgroup"
|
|
|
|
type linuxSystemService struct {
|
|
name string
|
|
detect func() bool
|
|
interactive func() bool
|
|
new func(i Interface, platform string, c *Config) (Service, error)
|
|
}
|
|
|
|
func (sc linuxSystemService) String() string {
|
|
return sc.name
|
|
}
|
|
func (sc linuxSystemService) Detect() bool {
|
|
return sc.detect()
|
|
}
|
|
func (sc linuxSystemService) Interactive() bool {
|
|
return sc.interactive()
|
|
}
|
|
func (sc linuxSystemService) New(i Interface, c *Config) (Service, error) {
|
|
return sc.new(i, sc.String(), c)
|
|
}
|
|
|
|
func init() {
|
|
ChooseSystem(linuxSystemService{
|
|
name: "linux-systemd",
|
|
detect: isSystemd,
|
|
interactive: func() bool {
|
|
is, _ := isInteractive()
|
|
return is
|
|
},
|
|
new: newSystemdService,
|
|
},
|
|
linuxSystemService{
|
|
name: "linux-upstart",
|
|
detect: isUpstart,
|
|
interactive: func() bool {
|
|
is, _ := isInteractive()
|
|
return is
|
|
},
|
|
new: newUpstartService,
|
|
},
|
|
linuxSystemService{
|
|
name: "unix-systemv",
|
|
detect: func() bool { return true },
|
|
interactive: func() bool {
|
|
is, _ := isInteractive()
|
|
return is
|
|
},
|
|
new: newSystemVService,
|
|
},
|
|
)
|
|
}
|
|
|
|
func isInteractive() (bool, error) {
|
|
// TODO: This is not true for user services.
|
|
inContainer, err := isInContainer(cgroupFile)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return os.Getppid() != 1 || inContainer, nil
|
|
}
|
|
|
|
// isInContainer checks if the service is being executed in docker or lxc
|
|
// container.
|
|
func isInContainer(cgroupPath string) (bool, error) {
|
|
const maxlines = 5 // maximum lines to scan
|
|
|
|
f, err := os.Open(cgroupPath)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
defer f.Close()
|
|
scan := bufio.NewScanner(f)
|
|
|
|
lines := 0
|
|
for scan.Scan() && !(lines > maxlines) {
|
|
if strings.Contains(scan.Text(), "docker") || strings.Contains(scan.Text(), "lxc") {
|
|
return true, nil
|
|
}
|
|
lines++
|
|
}
|
|
if err := scan.Err(); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
var tf = map[string]interface{}{
|
|
"cmd": func(s string) string {
|
|
return `"` + strings.Replace(s, `"`, `\"`, -1) + `"`
|
|
},
|
|
"cmdEscape": func(s string) string {
|
|
return strings.Replace(s, " ", `\x20`, -1)
|
|
},
|
|
}
|