Skip to content
Permalink
Browse files

Fix systemd service implementation to not fallback to sysv (#319) (#374)

The current service_systemd.go implementation is falling back to use the
sysvinit one (service_init.go) when the commands give an error exit code.

This is wrong, because systemd should have either generated a service
file for those sysvinit init scripts, or systemd itself or the admin
might have disabled or masked those services, so falling back will give
the wrong result. Because it will definitely not pay attention to those
sysvinit services outside of its compat support anyway, so either
systemctl knows about them, or for all practical purposes it does not
matter at all.

This affects at least any Debian system starting with stretch (9.x).
We check for any older system and only fallback when using a legacy
systemd.

Of course if there is no need to have transparent goss definitions that
should work on services provided by either sysvinit or systemd, then an
option is to hardcode the systemd full service name as in <unit>.socket,
<unit>.service, or similar, which means the sysvinit fallback will
always fail, and we will then preserve the failure from systemd.
  • Loading branch information...
guillemj authored and aelsabbahy committed May 22, 2019
1 parent ed797be commit aa58d493ed0effbd8373d0a2a08ec0c5766c676e
Showing with 45 additions and 12 deletions.
  1. +26 −12 system/service_systemd.go
  2. +19 −0 system/system.go
@@ -9,6 +9,7 @@ import (

type ServiceSystemd struct {
service string
legacy bool
}

func NewServiceSystemd(service string, system *System, config util.Config) Service {
@@ -17,6 +18,13 @@ func NewServiceSystemd(service string, system *System, config util.Config) Servi
}
}

func NewServiceSystemdLegacy(service string, system *System, config util.Config) Service {
return &ServiceSystemd{
service: service,
legacy: true,
}
}

func (s *ServiceSystemd) Service() string {
return s.service
}
@@ -30,10 +38,12 @@ func (s *ServiceSystemd) Exists() (bool, error) {
if strings.Contains(cmd.Stdout.String(), fmt.Sprintf("%s.service", s.service)) {
return true, cmd.Err
}
// Fallback on sysv
sysv := &ServiceInit{service: s.service}
if e, err := sysv.Exists(); e && err == nil {
return true, nil
if s.legacy {
// Fallback on sysv
sysv := &ServiceInit{service: s.service}
if e, err := sysv.Exists(); e && err == nil {
return true, nil
}
}
return false, nil
}
@@ -47,10 +57,12 @@ func (s *ServiceSystemd) Enabled() (bool, error) {
if cmd.Status == 0 {
return true, cmd.Err
}
// Fallback on sysv
sysv := &ServiceInit{service: s.service}
if en, err := sysv.Enabled(); en && err == nil {
return true, nil
if s.legacy {
// Fallback on sysv
sysv := &ServiceInit{service: s.service}
if en, err := sysv.Enabled(); en && err == nil {
return true, nil
}
}
return false, nil
}
@@ -64,10 +76,12 @@ func (s *ServiceSystemd) Running() (bool, error) {
if cmd.Status == 0 {
return true, cmd.Err
}
// Fallback on sysv
sysv := &ServiceInit{service: s.service}
if r, err := sysv.Running(); r && err == nil {
return true, nil
if s.legacy {
// Fallback on sysv
sysv := &ServiceInit{service: s.service}
if r, err := sysv.Running(); r && err == nil {
return true, nil
}
}
return false, nil
}
@@ -2,6 +2,7 @@ package system

import (
"bytes"
"strconv"
"io/ioutil"
"os"
"os/exec"
@@ -100,6 +101,8 @@ func (sys *System) detectService() {
sys.NewService = NewServiceUpstart
case "systemd":
sys.NewService = NewServiceSystemd
case "systemdlegacy":
sys.NewService = NewServiceSystemdLegacy
case "alpineinit":
sys.NewService = NewAlpineServiceInit
default:
@@ -138,6 +141,9 @@ func DetectPackageManager() string {
// decide, it returns "init".
func DetectService() string {
if HasCommand("systemctl") {
if isLegacySystemd() {
return "systemdlegacy"
}
return "systemd"
}
// Centos Docker container doesn't run systemd, so we detect it or use init.
@@ -178,6 +184,19 @@ func HasCommand(cmd string) bool {
return false
}

func isLegacySystemd() bool {
if b, err := ioutil.ReadFile("/etc/debian_version"); err == nil {
i := bytes.Index(b, []byte("."))
if i < 0 {
return false
}
if major, err := strconv.Atoi(string(b[:i])); err == nil {
return major < 9
}
}
return false
}

func isRedhat() bool {
if _, err := os.Stat("/etc/redhat-release"); err == nil {
return true

0 comments on commit aa58d49

Please sign in to comment.
You can’t perform that action at this time.