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 +}