diff --git a/daemon/top_unix.go b/daemon/top_unix.go index 28cfb370d8..7854d2376f 100644 --- a/daemon/top_unix.go +++ b/daemon/top_unix.go @@ -113,6 +113,20 @@ func parsePSOutput(output []byte, procs []uint32) (*container.ContainerTopOKBody return procList, nil } +// psPidsArg converts a slice of PIDs to a string consisting +// of comma-separated list of PIDs prepended by "-q". +// For example, psPidsArg([]uint32{1,2,3}) returns "-q1,2,3". +func psPidsArg(pids []uint32) string { + b := []byte{'-', 'q'} + for i, p := range pids { + b = strconv.AppendUint(b, uint64(p), 10) + if i < len(pids)-1 { + b = append(b, ',') + } + } + return string(b) +} + // ContainerTop lists the processes running inside of the given // container by calling ps with the given args, or with the flags // "-ef" if no args are given. An error is returned if the container @@ -145,9 +159,16 @@ func (daemon *Daemon) ContainerTop(name string, psArgs string) (*container.Conta return nil, err } - output, err := exec.Command("ps", strings.Split(psArgs, " ")...).Output() + args := strings.Split(psArgs, " ") + pids := psPidsArg(procs) + output, err := exec.Command("ps", append(args, pids)...).Output() if err != nil { - return nil, fmt.Errorf("Error running ps: %v", err) + // some ps options (such as f) can't be used together with q, + // so retry without it + output, err = exec.Command("ps", args...).Output() + if err != nil { + return nil, fmt.Errorf("Error running ps: %v", err) + } } procList, err := parsePSOutput(output, procs) if err != nil {