From b5d0021fb62e58d27355e42a41eb6ba5eb834144 Mon Sep 17 00:00:00 2001 From: Clement Sam Date: Tue, 13 Dec 2022 10:12:24 +0000 Subject: [PATCH] cmd/storagenode-updater: restart storagenode after update on BSD unix derivatives On BSD, the storagenode-updater falls back to renaming the storagenode without doing anything to restart the service. Like the approach we have for linux, this change finds the process ID of the storagenode using pgrep and sends an interrupt signal to the process. Closes https://github.com/storj/storj/issues/5333 Change-Id: Icced90ea3e831528804784c2170a3b8b14952e8c --- cmd/storagenode-updater/restart.go | 4 +- cmd/storagenode-updater/restart_bsd.go | 80 ++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 cmd/storagenode-updater/restart_bsd.go diff --git a/cmd/storagenode-updater/restart.go b/cmd/storagenode-updater/restart.go index ead1c5eb9..9d706084d 100644 --- a/cmd/storagenode-updater/restart.go +++ b/cmd/storagenode-updater/restart.go @@ -1,8 +1,8 @@ // Copyright (C) 2020 Storj Labs, Inc. // See LICENSE for copying information. -//go:build !service || (!windows && !linux && service) -// +build !service !windows,!linux,service +//go:build !service || (!windows && !linux && !freebsd && !dragonfly && !netbsd && !openbsd && !solaris && !darwin && service) +// +build !service !windows,!linux,!freebsd,!dragonfly,!netbsd,!openbsd,!solaris,!darwin,service package main diff --git a/cmd/storagenode-updater/restart_bsd.go b/cmd/storagenode-updater/restart_bsd.go new file mode 100644 index 000000000..9a2291fdc --- /dev/null +++ b/cmd/storagenode-updater/restart_bsd.go @@ -0,0 +1,80 @@ +// Copyright (C) 2020 Storj Labs, Inc. +// See LICENSE for copying information. + +//go:build service && (darwin || freebsd || dragonfly || netbsd || openbsd || solaris) +// +build service +// +build darwin freebsd dragonfly netbsd openbsd solaris + +package main + +import ( + "context" + "os" + "os/exec" + "strconv" + "strings" + + "github.com/spf13/cobra" + "github.com/zeebo/errs" +) + +func cmdRestart(cmd *cobra.Command, args []string) error { + return nil +} + +func restartService(ctx context.Context, service, binaryLocation, newVersionPath, backupPath string) error { + if err := os.Rename(binaryLocation, backupPath); err != nil { + return errs.Wrap(err) + } + + if err := os.Rename(newVersionPath, binaryLocation); err != nil { + return errs.Combine(err, os.Rename(backupPath, binaryLocation), os.Remove(newVersionPath)) + } + + if service == updaterServiceName { + os.Exit(1) + } + + if err := stopProcess(service); err != nil { + err = errs.New("error stopping %s service: %v", service, err) + return errs.Combine(err, os.Rename(backupPath, binaryLocation)) + } + + return nil +} + +func stopProcess(service string) (err error) { + pid, err := getServicePID(service) + if err != nil { + return err + } + p, err := os.FindProcess(pid) + if err != nil { + return err + } + return p.Signal(os.Interrupt) +} + +func getServicePID(service string) (int, error) { + args := []string{ + "-n", // only return the newest process (though we expect only one to be running) + "-x", // match the whole name + service, + } + + cmd := exec.Command("pgrep", args...) + + out, err := cmd.CombinedOutput() + if err != nil { + return 0, errs.New("Error retrieving service pid: pgrep: %s %v", string(out), err) + } + + trimmed := strings.TrimSuffix(string(out), "\n") + + pid, err := strconv.Atoi(trimmed) + if err != nil { + return 0, err + } + + return pid, nil +}