From c77907694d48c785b4b958616c04c42449faf302 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 18 Feb 2020 16:01:32 +0300 Subject: [PATCH] + service: support "-s reload" command --- home/home.go | 2 +- home/service.go | 49 ++++++++++++++++++++++++++++++++++++++++++++++ util/os_freebsd.go | 5 +++++ util/os_unix.go | 5 +++++ util/os_windows.go | 11 ++++++++++- 5 files changed, 70 insertions(+), 2 deletions(-) diff --git a/home/home.go b/home/home.go index 299653c4..ba01562e 100644 --- a/home/home.go +++ b/home/home.go @@ -528,7 +528,7 @@ func loadOptions() options { } o.bindPort = v }, nil}, - {"service", "s", "Service control action: status, install, uninstall, start, stop, restart", func(value string) { + {"service", "s", "Service control action: status, install, uninstall, start, stop, restart, reload (configuration)", func(value string) { o.serviceControlAction = value }, nil}, {"logfile", "l", "Path to log file. If empty: write to stdout; if 'syslog': write to system log", func(value string) { diff --git a/home/service.go b/home/service.go index d066e118..2cb31ecb 100644 --- a/home/service.go +++ b/home/service.go @@ -1,9 +1,11 @@ package home import ( + "fmt" "io/ioutil" "os" "runtime" + "strconv" "strings" "syscall" @@ -71,6 +73,48 @@ func svcAction(s service.Service, action string) error { return err } +// Send SIGHUP to a process with ID taken from our pid-file +// If pid-file doesn't exist, find our PID using 'ps' command +func sendSigReload() { + if runtime.GOOS == "windows" { + log.Error("Not implemented on Windows") + return + } + + pidfile := fmt.Sprintf("/var/run/%s.pid", serviceName) + data, err := ioutil.ReadFile(pidfile) + if os.IsNotExist(err) { + code, psdata, err := util.RunCommand("ps", "-C", serviceName, "-o", "pid=") + if err != nil || code != 0 { + log.Error("Can't find AdGuardHome process: %s code:%d", err, code) + return + } + data = []byte(psdata) + + } else if err != nil { + log.Error("Can't read PID file %s: %s", pidfile, err) + return + } + + parts := strings.SplitN(string(data), "\n", 2) + if len(parts) == 0 { + log.Error("Can't read PID file %s: bad value", pidfile) + return + } + + pid, err := strconv.Atoi(parts[0]) + if err != nil { + log.Error("Can't read PID file %s: %s", pidfile, err) + return + } + err = util.SendProcessSignal(pid, syscall.SIGHUP) + if err != nil { + log.Error("Can't send signal to PID %d: %s", pid, err) + return + } + log.Debug("Sent signal to PID %d", pid) +} + // handleServiceControlAction one of the possible control actions: // install -- installs a service/daemon // uninstall -- uninstalls it @@ -84,6 +128,11 @@ func svcAction(s service.Service, action string) error { func handleServiceControlAction(action string) { log.Printf("Service control action: %s", action) + if action == "reload" { + sendSigReload() + return + } + pwd, err := os.Getwd() if err != nil { log.Fatal("Unable to find the path to the current directory") diff --git a/util/os_freebsd.go b/util/os_freebsd.go index 33311e16..8254d897 100644 --- a/util/os_freebsd.go +++ b/util/os_freebsd.go @@ -25,3 +25,8 @@ func SetRlimit(val uint) { func HaveAdminRights() (bool, error) { return os.Getuid() == 0, nil } + +// SendProcessSignal - send signal to a process +func SendProcessSignal(pid int, sig syscall.Signal) error { + return syscall.Kill(pid, sig) +} diff --git a/util/os_unix.go b/util/os_unix.go index 338edfa8..9826a68c 100644 --- a/util/os_unix.go +++ b/util/os_unix.go @@ -25,3 +25,8 @@ func SetRlimit(val uint) { func HaveAdminRights() (bool, error) { return os.Getuid() == 0, nil } + +// SendProcessSignal - send signal to a process +func SendProcessSignal(pid int, sig syscall.Signal) error { + return syscall.Kill(pid, sig) +} diff --git a/util/os_windows.go b/util/os_windows.go index e081f758..1c09e588 100644 --- a/util/os_windows.go +++ b/util/os_windows.go @@ -1,6 +1,11 @@ package util -import "golang.org/x/sys/windows" +import ( + "fmt" + "syscall" + + "golang.org/x/sys/windows" +) // Set user-specified limit of how many fd's we can use func SetRlimit(val uint) { @@ -26,3 +31,7 @@ func HaveAdminRights() (bool, error) { } return true, nil } + +func SendProcessSignal(pid int, sig syscall.Signal) error { + return fmt.Errorf("not supported on Windows") +}