0a9ec218 |
//+build !windows
|
aa49632f |
package daemon
import (
"os/exec"
"strconv"
"strings"
|
a283a30f |
derr "github.com/docker/docker/errors" |
907407d0 |
"github.com/docker/engine-api/types" |
aa49632f |
)
|
abd72d40 |
// 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. |
b08f071e |
func (daemon *Daemon) ContainerTop(name string, psArgs string) (*types.ContainerProcessList, error) { |
3e096cb9 |
if psArgs == "" { |
aa49632f |
psArgs = "-ef"
}
|
d7d512bb |
container, err := daemon.GetContainer(name) |
d25a6537 |
if err != nil { |
3e096cb9 |
return nil, err |
d25a6537 |
} |
3e096cb9 |
|
d25a6537 |
if !container.IsRunning() { |
f7d4b4fe |
return nil, derr.ErrorCodeNotRunning.WithArgs(name) |
d25a6537 |
} |
3e096cb9 |
|
b08f071e |
pids, err := daemon.ExecutionDriver().GetPidsForContainer(container.ID) |
d25a6537 |
if err != nil { |
3e096cb9 |
return nil, err |
d25a6537 |
} |
3e096cb9 |
|
d25a6537 |
output, err := exec.Command("ps", strings.Split(psArgs, " ")...).Output()
if err != nil { |
f7d4b4fe |
return nil, derr.ErrorCodePSError.WithArgs(err) |
d25a6537 |
} |
aa49632f |
|
3e096cb9 |
procList := &types.ContainerProcessList{}
|
d25a6537 |
lines := strings.Split(string(output), "\n") |
3e096cb9 |
procList.Titles = strings.Fields(lines[0]) |
aa49632f |
|
d25a6537 |
pidIndex := -1 |
3e096cb9 |
for i, name := range procList.Titles { |
d25a6537 |
if name == "PID" {
pidIndex = i |
aa49632f |
} |
d25a6537 |
}
if pidIndex == -1 { |
f7d4b4fe |
return nil, derr.ErrorCodeNoPID |
d25a6537 |
} |
aa49632f |
|
abd72d40 |
// loop through the output and extract the PID from each line |
d25a6537 |
for _, line := range lines[1:] {
if len(line) == 0 {
continue
}
fields := strings.Fields(line)
p, err := strconv.Atoi(fields[pidIndex])
if err != nil { |
f7d4b4fe |
return nil, derr.ErrorCodeBadPID.WithArgs(fields[pidIndex], err) |
d25a6537 |
} |
aa49632f |
|
d25a6537 |
for _, pid := range pids {
if pid == p {
// Make sure number of fields equals number of header titles
// merging "overhanging" fields |
3e096cb9 |
process := fields[:len(procList.Titles)-1]
process = append(process, strings.Join(fields[len(procList.Titles)-1:], " "))
procList.Processes = append(procList.Processes, process) |
aa49632f |
}
}
} |
ca5ede2d |
daemon.LogContainerEvent(container, "top") |
3e096cb9 |
return procList, nil |
aa49632f |
} |