mirror of
https://github.com/containers/podman.git
synced 2025-10-25 18:25:59 +08:00
top: make output tabular
Make the output of top tabular to be compatible with Docker. Please note, that any user-input for `GetContainerPidInformation(...)` will be ignored until we have found a way to generically and reliably parse ps-1 output or until there is a go-lib to extract all the data from /proc in a ps-1 compatible fashion. Fixes: #458 Signed-off-by: Valentin Rothberg <vrothberg@suse.com> Closes: #939 Approved by: rhatdan
This commit is contained in:
committed by
Atomic Bot
parent
9e134576e8
commit
b1e709806d
@ -2,6 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectatomic/libpod/cmd/podman/libpodruntime"
|
||||
@ -34,8 +36,7 @@ func topCmd(c *cli.Context) error {
|
||||
var container *libpod.Container
|
||||
var err error
|
||||
args := c.Args()
|
||||
var psArgs []string
|
||||
psOpts := []string{"-o", "uid,pid,ppid,c,stime,tname,time,cmd"}
|
||||
|
||||
if len(args) < 1 && !c.Bool("latest") {
|
||||
return errors.Errorf("you must provide the name or id of a running container")
|
||||
}
|
||||
@ -48,9 +49,6 @@ func topCmd(c *cli.Context) error {
|
||||
return errors.Wrapf(err, "error creating libpod runtime")
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
if len(args) > 1 {
|
||||
psOpts = args[1:]
|
||||
}
|
||||
|
||||
if c.Bool("latest") {
|
||||
container, err = runtime.GetLatestContainer()
|
||||
@ -69,14 +67,15 @@ func topCmd(c *cli.Context) error {
|
||||
return errors.Errorf("top can only be used on running containers")
|
||||
}
|
||||
|
||||
psArgs = append(psArgs, psOpts...)
|
||||
|
||||
psOutput, err := container.GetContainerPidInformation(psArgs)
|
||||
psOutput, err := container.GetContainerPidInformation([]string{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, line := range psOutput {
|
||||
fmt.Println(line)
|
||||
|
||||
w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0)
|
||||
for _, proc := range psOutput {
|
||||
fmt.Fprintln(w, proc)
|
||||
}
|
||||
w.Flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -44,8 +44,20 @@ func (c *Container) getContainerPids() ([]string, error) {
|
||||
}
|
||||
|
||||
// GetContainerPidInformation calls ps with the appropriate options and returns
|
||||
// the results as a string and the container's PIDs as a []string
|
||||
// the results as a string and the container's PIDs as a []string. Note that
|
||||
// the ps output columns of each string are separated by a '\t\'. Currently,
|
||||
// the args argument is overwriten with []string{"-ef"} until there is a
|
||||
// portable library for ps-1 or to parse the procFS to extract all data.
|
||||
func (c *Container) GetContainerPidInformation(args []string) ([]string, error) {
|
||||
// XXX(ps-issue): args is overwriten with []{"-ef"} as the ps-1 tool
|
||||
// doesn't support a generic way of splitting columns, rendering its
|
||||
// output hard to parse. Docker first deterimes the number of columns
|
||||
// and merges all exceeding ones into the last one. We believe that
|
||||
// writing a go library which parses procFS in a ps-compatible way may
|
||||
// be more beneficial in the long run. Until then, args will be
|
||||
// ignored.
|
||||
args = []string{"-ef"}
|
||||
|
||||
if !c.batched {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
@ -80,7 +92,7 @@ func filterPids(psOutput string, pids []string) ([]string, error) {
|
||||
// Pids that don't belong.
|
||||
|
||||
// append the headers back in
|
||||
output = append(output, results[0])
|
||||
output = append(output, strings.Join(headers, "\t"))
|
||||
|
||||
pidIndex := -1
|
||||
for i, header := range headers {
|
||||
@ -98,7 +110,13 @@ func filterPids(psOutput string, pids []string) ([]string, error) {
|
||||
cols := fieldsASCII(l)
|
||||
pid := cols[pidIndex]
|
||||
if util.StringInSlice(pid, pids) {
|
||||
output = append(output, l)
|
||||
// XXX(ps-issue): Strip cols down to the header's size
|
||||
// and merge exceeding fields. This is required to
|
||||
// "merge" the overhanging CMD entries which can
|
||||
// contain white spaces.
|
||||
out := cols[:len(headers)-1]
|
||||
out = append(out, strings.Join(cols[len(headers)-1:], " "))
|
||||
output = append(output, strings.Join(out, "\t"))
|
||||
}
|
||||
}
|
||||
return output, nil
|
||||
|
||||
@ -59,7 +59,14 @@ var _ = Describe("Podman top", func() {
|
||||
Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1))
|
||||
})
|
||||
|
||||
// XXX(ps-issue): for the time being, podman-top and the libpod API
|
||||
// GetContainerPidInformation(...) will ignore any arguments passed to ps,
|
||||
// so we have to disable the tests below. Please refer to
|
||||
// https://github.com/projectatomic/libpod/pull/939 for more background
|
||||
// information.
|
||||
|
||||
It("podman top with options", func() {
|
||||
Skip("podman-top with options: options are temporarily ignored")
|
||||
session := podmanTest.Podman([]string{"run", "-d", ALPINE, "top", "-d", "2"})
|
||||
session.WaitWithDefaultTimeout()
|
||||
Expect(session.ExitCode()).To(Equal(0))
|
||||
@ -71,6 +78,7 @@ var _ = Describe("Podman top", func() {
|
||||
})
|
||||
|
||||
It("podman top on container invalid options", func() {
|
||||
Skip("podman-top with invalid options: options are temporarily ignored")
|
||||
top := podmanTest.RunTopContainer("")
|
||||
top.WaitWithDefaultTimeout()
|
||||
Expect(top.ExitCode()).To(Equal(0))
|
||||
|
||||
Reference in New Issue
Block a user