func (s *Service) getProcessStrings(pids []int32, ages []time.Time) (min, max, age, pid string) {
	if min = "min: 1"; s.proc.countMin > 0 {  
		min = fmt.Sprintf("min: %d", s.proc.countMin)
	}
	if s.proc.countMax > 0 {
		max = fmt.Sprintf(", max: %d", s.proc.countMax)
	}
	if len(ages) == 1 && !ages[0].IsZero() {
		age = fmt.Sprintf(", age: %v", durafmt.ParseShort(time.Since(ages[0]).Round(time.Second)))
	}
	for _, p := range pids {
		if pid == "" {
			pid = ", pids: "
		} else {
			pid += ";"
		}
		pid += fmt.Sprintf("%v", p)
	}
	return
}
getProcessStrings compiles output strings for a process service check.
package services
import (
	"context"
	"fmt"
	"regexp"
	"runtime"
	"strings"
	"time"
	"github.com/hako/durafmt"
	"github.com/shirou/gopsutil/v3/process"
)
type ProcInfo struct {
	CmdLine string
	Created time.Time
	PID     int32
}
type procExpect struct {
	checkRE  *regexp.Regexp
	countMin int
	countMax int
	restarts bool
	running  bool
}
const epochOffset = 1000
func GetAllProcesses() ([]*ProcInfo, error) {
	ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
	defer cancel()
	processes, err := process.ProcessesWithContext(ctx)
	if err != nil {
		return nil, fmt.Errorf("getting process list: %w", err)
	}
	p := []*ProcInfo{}
	for _, proc := range processes {
		procinfo, errs := getProcInfo(ctx, proc)
		if len(errs) != 0 {
			if procinfo == nil || procinfo.CmdLine == "" {
				continue
			}
		}  
		procinfo.PID = proc.Pid
		p = append(p, procinfo)
	}
	return p, nil
}
func (s *Service) checkProccess() *result {
	ctx, cancel := context.WithTimeout(context.Background(), s.Timeout.Duration)
	defer cancel()
	processes, err := process.ProcessesWithContext(ctx)
	if err != nil {
		return &result{
			state:  StateUnknown,
			output: "process list error: " + err.Error(),
		}
	}
	return s.getProcessResults(ctx, processes)
}
func (s *Service) getProcessResults(ctx context.Context, processes []*process.Process) *result {
	var (
		found []int32
		ages  []time.Time
	)
	for _, proc := range processes {
		procinfo, _ := getProcInfo(ctx, proc)
		if procinfo.CmdLine == "" {
			continue
		}
		if strings.Contains(procinfo.CmdLine, s.Value) ||
			(s.proc.checkRE != nil && s.proc.checkRE.FindString(procinfo.CmdLine) != "") {
			found = append(found, proc.Pid)
			ages = append(ages, procinfo.Created)
			if !procinfo.Created.IsZero() && s.proc.restarts && time.Since(procinfo.Created) < s.Interval.Duration {
				return &result{
					state: StateCritical,
					output: fmt.Sprintf("%s: process restarted since last check, age: %v, pid: %d, proc: %s",
						s.Value, time.Since(procinfo.Created), proc.Pid, procinfo.CmdLine),
				}
			}
		}
	}
	return s.checkProcessCounts(found, ages)
}
func (s *Service) checkProcessCounts(pids []int32, ages []time.Time) *result {
	min, max, age, pid := s.getProcessStrings(pids, ages)
	switch count := len(pids); {
	case !s.proc.running && count == 0:  
		fallthrough
	case s.proc.countMax != 0 && count > s.proc.countMax:  
		fallthrough
	case count < s.proc.countMin:  
		return &result{
			state:  StateCritical,
			output: fmt.Sprintf("%s: found %d processes; %s%s%s%s", s.Value, count, min, max, age, pid),
		}
	case s.proc.running && count > 0:  
		return &result{
			state:  StateCritical,
			output: fmt.Sprintf("%s: found %d processes; expected: 0%s%s", s.Value, count, age, pid),
		}
	default:  
		return &result{
			state:  StateOK,
			output: fmt.Sprintf("%s: found %d processes; %s%s%s%s", s.Value, count, min, max, age, pid),
		}
	}
}