From a41328d5704b8d1adbcd099fb4bb0697060df806 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Tue, 22 May 2018 17:09:41 -0700 Subject: [PATCH] ContainerTop: improve error message If "ps" fails, in many cases it prints a meaningful error message which a user can benefit from. Let's use it. While at it, let's use errdefs.System to classify the error, as well as errors.Wrap. Before: > $ docker top $CT > Error response from daemon: Error running ps: exit status 1 After: > $ docker top $CT auxm > Error response from daemon: ps: error: thread display conflicts with forest display or > $ docker top $CT saur > Error response from daemon: ps: error: conflicting format options or, if there's no meaningful error on stderr, same as before: > $ docker top $CT 1234 > Error response from daemon: ps: exit status 1 Signed-off-by: Kir Kolyshkin --- daemon/top_unix.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/daemon/top_unix.go b/daemon/top_unix.go index 7854d2376f..99ca56f0f4 100644 --- a/daemon/top_unix.go +++ b/daemon/top_unix.go @@ -3,6 +3,7 @@ package daemon // import "github.com/docker/docker/daemon" import ( + "bytes" "context" "fmt" "os/exec" @@ -11,6 +12,8 @@ import ( "strings" "github.com/docker/docker/api/types/container" + "github.com/docker/docker/errdefs" + "github.com/pkg/errors" ) func validatePSArgs(psArgs string) error { @@ -167,7 +170,14 @@ func (daemon *Daemon) ContainerTop(name string, psArgs string) (*container.Conta // so retry without it output, err = exec.Command("ps", args...).Output() if err != nil { - return nil, fmt.Errorf("Error running ps: %v", err) + if ee, ok := err.(*exec.ExitError); ok { + // first line of stderr shows why ps failed + line := bytes.SplitN(ee.Stderr, []byte{'\n'}, 2) + if len(line) > 0 && len(line[0]) > 0 { + err = errors.New(string(line[0])) + } + } + return nil, errdefs.System(errors.Wrap(err, "ps")) } } procList, err := parsePSOutput(output, procs)