mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
27c76522de
Avoid creating a global context object that will be used while the daemon is running. Not only this object won't ever be garbage collected, but it won't ever be used for anything else than creating other contexts in each request. I think it's a bad practive to have something like this sprawling aroud the code. This change removes that global object and initializes a context in the cases we don't have already one, like shutting down the server. This also removes a bunch of context arguments from functions that did nothing with it. Signed-off-by: David Calavera <david.calavera@gmail.com>
82 lines
2 KiB
Go
82 lines
2 KiB
Go
//+build !windows
|
|
|
|
package daemon
|
|
|
|
import (
|
|
"os/exec"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/docker/docker/context"
|
|
derr "github.com/docker/docker/errors"
|
|
)
|
|
|
|
// 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
|
|
// is not found, or is not running, or if there are any problems
|
|
// running ps, or parsing the output.
|
|
func (daemon *Daemon) ContainerTop(ctx context.Context, name string, psArgs string) (*types.ContainerProcessList, error) {
|
|
if psArgs == "" {
|
|
psArgs = "-ef"
|
|
}
|
|
|
|
container, err := daemon.Get(ctx, name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !container.IsRunning() {
|
|
return nil, derr.ErrorCodeNotRunning.WithArgs(name)
|
|
}
|
|
|
|
pids, err := daemon.ExecutionDriver().GetPidsForContainer(container.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
output, err := exec.Command("ps", strings.Split(psArgs, " ")...).Output()
|
|
if err != nil {
|
|
return nil, derr.ErrorCodePSError.WithArgs(err)
|
|
}
|
|
|
|
procList := &types.ContainerProcessList{}
|
|
|
|
lines := strings.Split(string(output), "\n")
|
|
procList.Titles = strings.Fields(lines[0])
|
|
|
|
pidIndex := -1
|
|
for i, name := range procList.Titles {
|
|
if name == "PID" {
|
|
pidIndex = i
|
|
}
|
|
}
|
|
if pidIndex == -1 {
|
|
return nil, derr.ErrorCodeNoPID
|
|
}
|
|
|
|
// loop through the output and extract the PID from each line
|
|
for _, line := range lines[1:] {
|
|
if len(line) == 0 {
|
|
continue
|
|
}
|
|
fields := strings.Fields(line)
|
|
p, err := strconv.Atoi(fields[pidIndex])
|
|
if err != nil {
|
|
return nil, derr.ErrorCodeBadPID.WithArgs(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(procList.Titles)-1]
|
|
process = append(process, strings.Join(fields[len(procList.Titles)-1:], " "))
|
|
procList.Processes = append(procList.Processes, process)
|
|
}
|
|
}
|
|
}
|
|
container.logEvent(ctx, "top")
|
|
return procList, nil
|
|
}
|