36b3af2e3d
PR Check / Code Quality: Format (push) Failing after 1s
PR Check / Code Quality: Lint (darwin) (push) Failing after 0s
PR Check / Code Quality: Lint (freebsd) (push) Failing after 1s
PR Check / Code Quality: Lint (windows) (push) Failing after 1s
PR Check / Code Quality: Lint (linux) (push) Failing after 1s
PR Check / Security: Vulnerability Scan (push) Failing after 0s
Update Documentation / update-docs (push) Failing after 2s
PR Check / Code Quality: Vendor (push) Failing after 1s
PR Check / Code Quality: Coverage (push) Failing after 0s
PR Check / Tests: Unit (macos-latest) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04) (push) Has been cancelled
PR Check / Tests: Unit (ubuntu-24.04-arm) (push) Has been cancelled
PR Check / Tests: Unit (windows-latest) (push) Has been cancelled
100 lines
2.3 KiB
Go
100 lines
2.3 KiB
Go
package source
|
|
|
|
import (
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/pranshuparmar/witr/pkg/model"
|
|
)
|
|
|
|
var knownSupervisors = map[string]string{
|
|
"pm2": "pm2",
|
|
"supervisord": "supervisord",
|
|
"supervisor": "supervisord",
|
|
"gunicorn": "gunicorn",
|
|
"uwsgi": "uwsgi",
|
|
"s6-supervise": "s6",
|
|
"s6": "s6",
|
|
"s6-svscan": "s6",
|
|
"runsv": "runit",
|
|
"runit": "runit",
|
|
"runit-init": "runit",
|
|
"openrc": "openrc",
|
|
"openrc-init": "openrc",
|
|
"monit": "monit",
|
|
"circusd": "circus",
|
|
"circus": "circus",
|
|
"systemd": "systemd service",
|
|
"systemctl": "systemd service",
|
|
"daemontools": "daemontools",
|
|
"initctl": "upstart",
|
|
"tini": "tini",
|
|
"docker-init": "docker-init",
|
|
"podman-init": "podman-init",
|
|
"smf": "smf",
|
|
"launchd": "launchd",
|
|
"god": "god",
|
|
"forever": "forever",
|
|
"nssm": "nssm",
|
|
}
|
|
|
|
func detectSupervisor(ancestry []model.Process) *model.Source {
|
|
// Check if there's a shell in the ancestry
|
|
hasShell := false
|
|
for _, p := range ancestry {
|
|
if isShell(strings.ToLower(filepath.Base(p.Command))) {
|
|
hasShell = true
|
|
break
|
|
}
|
|
}
|
|
|
|
for _, p := range ancestry {
|
|
base := filepath.Base(p.Command)
|
|
if base == "init" {
|
|
if !hasShell {
|
|
return &model.Source{
|
|
Type: model.SourceSupervisor,
|
|
Name: "init",
|
|
}
|
|
}
|
|
}
|
|
|
|
if label, ok := knownSupervisors[strings.ToLower(base)]; ok {
|
|
if label == "init" && hasShell {
|
|
continue
|
|
}
|
|
return &model.Source{
|
|
Type: model.SourceSupervisor,
|
|
Name: label,
|
|
}
|
|
}
|
|
// Match individual tokens from the cmdline against supervisor keys
|
|
if label := matchCmdlineTokens(p.Cmdline, hasShell); label != "" {
|
|
return &model.Source{
|
|
Type: model.SourceSupervisor,
|
|
Name: label,
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// matchCmdlineTokens extracts the executable basename and each argument token
|
|
// from a command line, then looks up each against knownSupervisors by exact match.
|
|
func matchCmdlineTokens(cmdline string, hasShell bool) string {
|
|
for _, token := range strings.Fields(strings.ToLower(cmdline)) {
|
|
// Skip flags and env assignments
|
|
if strings.HasPrefix(token, "-") || strings.Contains(token, "=") {
|
|
continue
|
|
}
|
|
base := filepath.Base(token)
|
|
if label, ok := knownSupervisors[base]; ok {
|
|
if label == "init" && hasShell {
|
|
continue
|
|
}
|
|
return label
|
|
}
|
|
}
|
|
return ""
|
|
}
|