container.go 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // DEPRECATION NOTICE. PLEASE DO NOT ADD ANYTHING TO THIS FILE.
  2. //
  3. // For additional commments see server/server.go
  4. //
  5. package server
  6. import (
  7. "errors"
  8. "fmt"
  9. "os/exec"
  10. "strconv"
  11. "strings"
  12. "github.com/docker/docker/daemon"
  13. "github.com/docker/docker/engine"
  14. "github.com/docker/docker/pkg/graphdb"
  15. )
  16. func (srv *Server) ContainerTop(job *engine.Job) engine.Status {
  17. if len(job.Args) != 1 && len(job.Args) != 2 {
  18. return job.Errorf("Not enough arguments. Usage: %s CONTAINER [PS_ARGS]\n", job.Name)
  19. }
  20. var (
  21. name = job.Args[0]
  22. psArgs = "-ef"
  23. )
  24. if len(job.Args) == 2 && job.Args[1] != "" {
  25. psArgs = job.Args[1]
  26. }
  27. if container := srv.daemon.Get(name); container != nil {
  28. if !container.State.IsRunning() {
  29. return job.Errorf("Container %s is not running", name)
  30. }
  31. pids, err := srv.daemon.ExecutionDriver().GetPidsForContainer(container.ID)
  32. if err != nil {
  33. return job.Error(err)
  34. }
  35. output, err := exec.Command("ps", psArgs).Output()
  36. if err != nil {
  37. return job.Errorf("Error running ps: %s", err)
  38. }
  39. lines := strings.Split(string(output), "\n")
  40. header := strings.Fields(lines[0])
  41. out := &engine.Env{}
  42. out.SetList("Titles", header)
  43. pidIndex := -1
  44. for i, name := range header {
  45. if name == "PID" {
  46. pidIndex = i
  47. }
  48. }
  49. if pidIndex == -1 {
  50. return job.Errorf("Couldn't find PID field in ps output")
  51. }
  52. processes := [][]string{}
  53. for _, line := range lines[1:] {
  54. if len(line) == 0 {
  55. continue
  56. }
  57. fields := strings.Fields(line)
  58. p, err := strconv.Atoi(fields[pidIndex])
  59. if err != nil {
  60. return job.Errorf("Unexpected pid '%s': %s", fields[pidIndex], err)
  61. }
  62. for _, pid := range pids {
  63. if pid == p {
  64. // Make sure number of fields equals number of header titles
  65. // merging "overhanging" fields
  66. process := fields[:len(header)-1]
  67. process = append(process, strings.Join(fields[len(header)-1:], " "))
  68. processes = append(processes, process)
  69. }
  70. }
  71. }
  72. out.SetJson("Processes", processes)
  73. out.WriteTo(job.Stdout)
  74. return engine.StatusOK
  75. }
  76. return job.Errorf("No such container: %s", name)
  77. }
  78. func (srv *Server) ContainerChanges(job *engine.Job) engine.Status {
  79. if n := len(job.Args); n != 1 {
  80. return job.Errorf("Usage: %s CONTAINER", job.Name)
  81. }
  82. name := job.Args[0]
  83. if container := srv.daemon.Get(name); container != nil {
  84. outs := engine.NewTable("", 0)
  85. changes, err := container.Changes()
  86. if err != nil {
  87. return job.Error(err)
  88. }
  89. for _, change := range changes {
  90. out := &engine.Env{}
  91. if err := out.Import(change); err != nil {
  92. return job.Error(err)
  93. }
  94. outs.Add(out)
  95. }
  96. if _, err := outs.WriteListTo(job.Stdout); err != nil {
  97. return job.Error(err)
  98. }
  99. } else {
  100. return job.Errorf("No such container: %s", name)
  101. }
  102. return engine.StatusOK
  103. }
  104. func (srv *Server) Containers(job *engine.Job) engine.Status {
  105. var (
  106. foundBefore bool
  107. displayed int
  108. all = job.GetenvBool("all")
  109. since = job.Getenv("since")
  110. before = job.Getenv("before")
  111. n = job.GetenvInt("limit")
  112. size = job.GetenvBool("size")
  113. )
  114. outs := engine.NewTable("Created", 0)
  115. names := map[string][]string{}
  116. srv.daemon.ContainerGraph().Walk("/", func(p string, e *graphdb.Entity) error {
  117. names[e.ID()] = append(names[e.ID()], p)
  118. return nil
  119. }, -1)
  120. var beforeCont, sinceCont *daemon.Container
  121. if before != "" {
  122. beforeCont = srv.daemon.Get(before)
  123. if beforeCont == nil {
  124. return job.Error(fmt.Errorf("Could not find container with name or id %s", before))
  125. }
  126. }
  127. if since != "" {
  128. sinceCont = srv.daemon.Get(since)
  129. if sinceCont == nil {
  130. return job.Error(fmt.Errorf("Could not find container with name or id %s", since))
  131. }
  132. }
  133. errLast := errors.New("last container")
  134. writeCont := func(container *daemon.Container) error {
  135. container.Lock()
  136. defer container.Unlock()
  137. if !container.State.IsRunning() && !all && n <= 0 && since == "" && before == "" {
  138. return nil
  139. }
  140. if before != "" && !foundBefore {
  141. if container.ID == beforeCont.ID {
  142. foundBefore = true
  143. }
  144. return nil
  145. }
  146. if n > 0 && displayed == n {
  147. return errLast
  148. }
  149. if since != "" {
  150. if container.ID == sinceCont.ID {
  151. return errLast
  152. }
  153. }
  154. displayed++
  155. out := &engine.Env{}
  156. out.Set("Id", container.ID)
  157. out.SetList("Names", names[container.ID])
  158. out.Set("Image", srv.daemon.Repositories().ImageName(container.Image))
  159. if len(container.Args) > 0 {
  160. args := []string{}
  161. for _, arg := range container.Args {
  162. if strings.Contains(arg, " ") {
  163. args = append(args, fmt.Sprintf("'%s'", arg))
  164. } else {
  165. args = append(args, arg)
  166. }
  167. }
  168. argsAsString := strings.Join(args, " ")
  169. out.Set("Command", fmt.Sprintf("\"%s %s\"", container.Path, argsAsString))
  170. } else {
  171. out.Set("Command", fmt.Sprintf("\"%s\"", container.Path))
  172. }
  173. out.SetInt64("Created", container.Created.Unix())
  174. out.Set("Status", container.State.String())
  175. str, err := container.NetworkSettings.PortMappingAPI().ToListString()
  176. if err != nil {
  177. return err
  178. }
  179. out.Set("Ports", str)
  180. if size {
  181. sizeRw, sizeRootFs := container.GetSize()
  182. out.SetInt64("SizeRw", sizeRw)
  183. out.SetInt64("SizeRootFs", sizeRootFs)
  184. }
  185. outs.Add(out)
  186. return nil
  187. }
  188. for _, container := range srv.daemon.List() {
  189. if err := writeCont(container); err != nil {
  190. if err != errLast {
  191. return job.Error(err)
  192. }
  193. break
  194. }
  195. }
  196. outs.ReverseSort()
  197. if _, err := outs.WriteListTo(job.Stdout); err != nil {
  198. return job.Error(err)
  199. }
  200. return engine.StatusOK
  201. }