AdguardTeam/AdGuardHome · error

ps finished with code

Error message

ps finished with code %d

What it means

PIDByCommand shells out to ps; if ps exits with a non-zero status code, this error reports that exit code. It means the ps invocation itself failed rather than that the target process was or wasn't found.

Solutions

  1. Run ps with the same arguments manually to see why it fails
  2. Install procps/psmisc in minimal containers
  3. If ps flags differ per-platform, adjust the executil invocation or patch the flags used
  4. Treat this as an environment problem: fix the host, don't retry the call
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := exec.LookPath("ps"); err != nil { return fmt.Errorf("ps unavailable: %w", err) }

Try / catch

if err != nil {
    var exitErr *exec.ExitError
    if errors.As(err, &exitErr) || strings.Contains(err.Error(), "ps finished with code") {
        // inspect environment; do not retry blindly
    }
}

Prevention

When it happens

Trigger: The ps child process exits non-zero — ps binary missing (shell returns 127), permission denied reading /proc for other users' processes, unsupported ps flags on busybox/macOS variants, or a hostile environment where ps aborts.

Common situations: Minimal Docker images (alpine/distroless) without procps installed; BSD/macOS ps with GNU-only flags; hardened systems hiding /proc entries.

Related errors


AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27). Data as JSON: /api/errors/473b456b94f60bdc. Report an issue: GitHub.

Appendix: source

Thrown at internal/aghos/os.go:111

	var instNum int
	pid, instNum, err = parsePSOutput(&stdoutBuf, command, except)
	if err != nil {
		return 0, err
	}

	switch instNum {
	case 0:
		// TODO(e.burkov):  Use constant error.
		return 0, fmt.Errorf("no %s instances found", command)
	case 1:
		// Go on.
	default:
		l.WarnContext(ctx, "instances found", "num", instNum, "command", command)
	}

	if runErr != nil {
		if code, ok := executil.ExitCodeFromError(runErr); ok {
			return 0, fmt.Errorf("ps finished with code %d", code)
		}

		return 0, fmt.Errorf("executing the command: %w", runErr)
	}

	return pid, nil
}

// parsePSOutput scans the output of ps searching the largest PID of the process
// associated with cmdName ignoring PIDs from ignore.  A valid line from r
// should look like these:
//
//	 123 ./example-cmd
//	1230 some/base/path/example-cmd
//	3210 example-cmd
func parsePSOutput(r io.Reader, cmdName string, ignore []int) (largest, instNum int, err error) {
	s := bufio.NewScanner(r)
	for s.Scan() {

View on GitHub (pinned to b41aefbe51)