wg-quicker/tools/pidof/pidof.go
Marvin Steadfast 8d389aa3ad
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
detects running pid only of it doesnt contain grep
2021-04-26 11:12:54 +02:00

88 lines
1.7 KiB
Go

package pidof
import (
"errors"
"fmt"
"os/exec"
"regexp"
"strconv"
"strings"
"syscall"
log "github.com/sirupsen/logrus"
)
//go:generate mockery --name Commander --inpackage --output .
var ErrPIDNotFound = fmt.Errorf("could not find pid")
type Commander interface {
Output(cmd string) ([]byte, error)
}
type Cdr struct{}
func (c Cdr) Output(cmd string) ([]byte, error) {
cm := exec.Command("/bin/sh", "-c", cmd)
log.WithField("cmd", cm.String()).Debug("command to run")
// nolint:wrapcheck
return cm.Output()
}
func Pidof(name string, cdr Commander) (int, error) {
p, err := cdr.Output(fmt.Sprintf("ps a|grep '%s'", name))
if err != nil {
log.WithField("output", p).Debug(p)
return 0, fmt.Errorf("could not execute ps command: %w", err)
}
for _, l := range strings.Split(string(p), "\n") {
if strings.Contains(l, name) && !strings.Contains(l, "grep") {
// nolint:gocritic
rePID, err := regexp.Compile(`(\d+)\s.+`)
if err != nil {
return 0, fmt.Errorf("could not compile re: %w", err)
}
matches := rePID.FindStringSubmatch(l)
// nolint: gomnd
if len(matches) == 2 {
pid, err := strconv.Atoi(matches[1])
if err != nil {
return 0, fmt.Errorf("could not convert string to int: %w", err)
}
return pid, nil
}
break
}
}
return 0, ErrPIDNotFound
}
func Pkill(name string) error {
c := Cdr{}
pid, err := Pidof(name, c)
if err != nil {
if errors.Is(err, ErrPIDNotFound) {
log.Debug("looks like the process is not running")
return nil
}
return fmt.Errorf("could not get pid: %w", err)
}
if err := syscall.Kill(pid, 9); err != nil {
return fmt.Errorf("could not kill process: %w", err)
}
return nil
}