mirror of https://github.com/docker/docs.git
220 lines
5.4 KiB
Go
220 lines
5.4 KiB
Go
// DEPRECATION NOTICE. PLEASE DO NOT ADD ANYTHING TO THIS FILE.
|
|
//
|
|
// For additional commments see server/server.go
|
|
//
|
|
package server
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os/exec"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/docker/docker/daemon"
|
|
"github.com/docker/docker/engine"
|
|
"github.com/docker/docker/pkg/graphdb"
|
|
)
|
|
|
|
func (srv *Server) ContainerTop(job *engine.Job) engine.Status {
|
|
if len(job.Args) != 1 && len(job.Args) != 2 {
|
|
return job.Errorf("Not enough arguments. Usage: %s CONTAINER [PS_ARGS]\n", job.Name)
|
|
}
|
|
var (
|
|
name = job.Args[0]
|
|
psArgs = "-ef"
|
|
)
|
|
|
|
if len(job.Args) == 2 && job.Args[1] != "" {
|
|
psArgs = job.Args[1]
|
|
}
|
|
|
|
if container := srv.daemon.Get(name); container != nil {
|
|
if !container.State.IsRunning() {
|
|
return job.Errorf("Container %s is not running", name)
|
|
}
|
|
pids, err := srv.daemon.ExecutionDriver().GetPidsForContainer(container.ID)
|
|
if err != nil {
|
|
return job.Error(err)
|
|
}
|
|
output, err := exec.Command("ps", psArgs).Output()
|
|
if err != nil {
|
|
return job.Errorf("Error running ps: %s", err)
|
|
}
|
|
|
|
lines := strings.Split(string(output), "\n")
|
|
header := strings.Fields(lines[0])
|
|
out := &engine.Env{}
|
|
out.SetList("Titles", header)
|
|
|
|
pidIndex := -1
|
|
for i, name := range header {
|
|
if name == "PID" {
|
|
pidIndex = i
|
|
}
|
|
}
|
|
if pidIndex == -1 {
|
|
return job.Errorf("Couldn't find PID field in ps output")
|
|
}
|
|
|
|
processes := [][]string{}
|
|
for _, line := range lines[1:] {
|
|
if len(line) == 0 {
|
|
continue
|
|
}
|
|
fields := strings.Fields(line)
|
|
p, err := strconv.Atoi(fields[pidIndex])
|
|
if err != nil {
|
|
return job.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err)
|
|
}
|
|
|
|
for _, pid := range pids {
|
|
if pid == p {
|
|
// Make sure number of fields equals number of header titles
|
|
// merging "overhanging" fields
|
|
process := fields[:len(header)-1]
|
|
process = append(process, strings.Join(fields[len(header)-1:], " "))
|
|
processes = append(processes, process)
|
|
}
|
|
}
|
|
}
|
|
out.SetJson("Processes", processes)
|
|
out.WriteTo(job.Stdout)
|
|
return engine.StatusOK
|
|
|
|
}
|
|
return job.Errorf("No such container: %s", name)
|
|
}
|
|
|
|
func (srv *Server) ContainerChanges(job *engine.Job) engine.Status {
|
|
if n := len(job.Args); n != 1 {
|
|
return job.Errorf("Usage: %s CONTAINER", job.Name)
|
|
}
|
|
name := job.Args[0]
|
|
if container := srv.daemon.Get(name); container != nil {
|
|
outs := engine.NewTable("", 0)
|
|
changes, err := container.Changes()
|
|
if err != nil {
|
|
return job.Error(err)
|
|
}
|
|
for _, change := range changes {
|
|
out := &engine.Env{}
|
|
if err := out.Import(change); err != nil {
|
|
return job.Error(err)
|
|
}
|
|
outs.Add(out)
|
|
}
|
|
if _, err := outs.WriteListTo(job.Stdout); err != nil {
|
|
return job.Error(err)
|
|
}
|
|
} else {
|
|
return job.Errorf("No such container: %s", name)
|
|
}
|
|
return engine.StatusOK
|
|
}
|
|
|
|
func (srv *Server) Containers(job *engine.Job) engine.Status {
|
|
var (
|
|
foundBefore bool
|
|
displayed int
|
|
all = job.GetenvBool("all")
|
|
since = job.Getenv("since")
|
|
before = job.Getenv("before")
|
|
n = job.GetenvInt("limit")
|
|
size = job.GetenvBool("size")
|
|
)
|
|
outs := engine.NewTable("Created", 0)
|
|
|
|
names := map[string][]string{}
|
|
srv.daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error {
|
|
names[e.ID()] = append(names[e.ID()], p)
|
|
return nil
|
|
}, -1)
|
|
|
|
var beforeCont, sinceCont *daemon.Container
|
|
if before != "" {
|
|
beforeCont = srv.daemon.Get(before)
|
|
if beforeCont == nil {
|
|
return job.Error(fmt.Errorf("Could not find container with name or id %s", before))
|
|
}
|
|
}
|
|
|
|
if since != "" {
|
|
sinceCont = srv.daemon.Get(since)
|
|
if sinceCont == nil {
|
|
return job.Error(fmt.Errorf("Could not find container with name or id %s", since))
|
|
}
|
|
}
|
|
|
|
errLast := errors.New("last container")
|
|
writeCont := func(container *daemon.Container) error {
|
|
container.Lock()
|
|
defer container.Unlock()
|
|
if !container.State.IsRunning() && !all && n <= 0 && since == "" && before == "" {
|
|
return nil
|
|
}
|
|
if before != "" && !foundBefore {
|
|
if container.ID == beforeCont.ID {
|
|
foundBefore = true
|
|
}
|
|
return nil
|
|
}
|
|
if n > 0 && displayed == n {
|
|
return errLast
|
|
}
|
|
if since != "" {
|
|
if container.ID == sinceCont.ID {
|
|
return errLast
|
|
}
|
|
}
|
|
displayed++
|
|
out := &engine.Env{}
|
|
out.Set("Id", container.ID)
|
|
out.SetList("Names", names[container.ID])
|
|
out.Set("Image", srv.daemon.Repositories().ImageName(container.Image))
|
|
if len(container.Args) > 0 {
|
|
args := []string{}
|
|
for _, arg := range container.Args {
|
|
if strings.Contains(arg, " ") {
|
|
args = append(args, fmt.Sprintf("'%s'", arg))
|
|
} else {
|
|
args = append(args, arg)
|
|
}
|
|
}
|
|
argsAsString := strings.Join(args, " ")
|
|
|
|
out.Set("Command", fmt.Sprintf("\"%s %s\"", container.Path, argsAsString))
|
|
} else {
|
|
out.Set("Command", fmt.Sprintf("\"%s\"", container.Path))
|
|
}
|
|
out.SetInt64("Created", container.Created.Unix())
|
|
out.Set("Status", container.State.String())
|
|
str, err := container.NetworkSettings.PortMappingAPI().ToListString()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
out.Set("Ports", str)
|
|
if size {
|
|
sizeRw, sizeRootFs := container.GetSize()
|
|
out.SetInt64("SizeRw", sizeRw)
|
|
out.SetInt64("SizeRootFs", sizeRootFs)
|
|
}
|
|
outs.Add(out)
|
|
return nil
|
|
}
|
|
|
|
for _, container := range srv.daemon.List() {
|
|
if err := writeCont(container); err != nil {
|
|
if err != errLast {
|
|
return job.Error(err)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
outs.ReverseSort()
|
|
if _, err := outs.WriteListTo(job.Stdout); err != nil {
|
|
return job.Error(err)
|
|
}
|
|
return engine.StatusOK
|
|
}
|