top.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package daemon
  2. import (
  3. "os/exec"
  4. "strconv"
  5. "strings"
  6. "github.com/docker/docker/engine"
  7. )
  8. func (daemon *Daemon) ContainerTop(job *engine.Job) engine.Status {
  9. if len(job.Args) != 1 && len(job.Args) != 2 {
  10. return job.Errorf("Not enough arguments. Usage: %s CONTAINER [PS_ARGS]\n", job.Name)
  11. }
  12. var (
  13. name = job.Args[0]
  14. psArgs = "-ef"
  15. )
  16. if len(job.Args) == 2 && job.Args[1] != "" {
  17. psArgs = job.Args[1]
  18. }
  19. if container := daemon.Get(name); container != nil {
  20. if !container.IsRunning() {
  21. return job.Errorf("Container %s is not running", name)
  22. }
  23. pids, err := daemon.ExecutionDriver().GetPidsForContainer(container.ID)
  24. if err != nil {
  25. return job.Error(err)
  26. }
  27. output, err := exec.Command("ps", strings.Split(psArgs, " ")...).Output()
  28. if err != nil {
  29. return job.Errorf("Error running ps: %s", err)
  30. }
  31. lines := strings.Split(string(output), "\n")
  32. header := strings.Fields(lines[0])
  33. out := &engine.Env{}
  34. out.SetList("Titles", header)
  35. pidIndex := -1
  36. for i, name := range header {
  37. if name == "PID" {
  38. pidIndex = i
  39. }
  40. }
  41. if pidIndex == -1 {
  42. return job.Errorf("Couldn't find PID field in ps output")
  43. }
  44. processes := [][]string{}
  45. for _, line := range lines[1:] {
  46. if len(line) == 0 {
  47. continue
  48. }
  49. fields := strings.Fields(line)
  50. p, err := strconv.Atoi(fields[pidIndex])
  51. if err != nil {
  52. return job.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err)
  53. }
  54. for _, pid := range pids {
  55. if pid == p {
  56. // Make sure number of fields equals number of header titles
  57. // merging "overhanging" fields
  58. process := fields[:len(header)-1]
  59. process = append(process, strings.Join(fields[len(header)-1:], " "))
  60. processes = append(processes, process)
  61. }
  62. }
  63. }
  64. out.SetJson("Processes", processes)
  65. out.WriteTo(job.Stdout)
  66. return engine.StatusOK
  67. }
  68. return job.Errorf("No such container: %s", name)
  69. }