Pārlūkot izejas kodu

add /proc to list running processes inside a container

Victor Vieux 12 gadi atpakaļ
vecāks
revīzija
2e79719622
5 mainītis faili ar 90 papildinājumiem un 1 dzēšanām
  1. 18 0
      api.go
  2. 7 0
      api_params.go
  3. 28 0
      commands.go
  4. 36 0
      server.go
  5. 1 1
      utils/utils.go

+ 18 - 0
api.go

@@ -250,6 +250,23 @@ func getContainersChanges(srv *Server, version float64, w http.ResponseWriter, r
 	return nil
 }
 
+func getContainersProc(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+	if vars == nil {
+		return fmt.Errorf("Missing parameter")
+	}
+	name := vars["name"]
+	procsStr, err := srv.ContainerProc(name)
+	if err != nil {
+		return err
+	}
+	b, err := json.Marshal(procsStr)
+	if err != nil {
+		return err
+	}
+	writeJSON(w, b)
+	return nil
+}
+
 func getContainersJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	if err := parseForm(r); err != nil {
 		return err
@@ -842,6 +859,7 @@ func createRouter(srv *Server, logging bool) (*mux.Router, error) {
 			"/containers/{name:.*}/export":  getContainersExport,
 			"/containers/{name:.*}/changes": getContainersChanges,
 			"/containers/{name:.*}/json":    getContainersByName,
+			"/containers/{name:.*}/proc":    getContainersProc,
 		},
 		"POST": {
 			"/auth":                         postAuth,

+ 7 - 0
api_params.go

@@ -26,6 +26,13 @@ type APIInfo struct {
 	SwapLimit   bool `json:",omitempty"`
 }
 
+type APIProc struct {
+	PID  string
+	Tty  string
+	Time string
+	Cmd  string
+}
+
 type APIRmi struct {
 	Deleted  string `json:",omitempty"`
 	Untagged string `json:",omitempty"`

+ 28 - 0
commands.go

@@ -90,6 +90,7 @@ func (cli *DockerCli) CmdHelp(args ...string) error {
 		{"login", "Register or Login to the docker registry server"},
 		{"logs", "Fetch the logs of a container"},
 		{"port", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT"},
+		{"proc", "Lookup the running processes of a container"},
 		{"ps", "List containers"},
 		{"pull", "Pull an image or a repository from the docker registry server"},
 		{"push", "Push an image or a repository to the docker registry server"},
@@ -555,6 +556,33 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
 	return nil
 }
 
+func (cli *DockerCli) CmdProc(args ...string) error {
+	cmd := Subcmd("proc", "CONTAINER", "Lookup the running processes of a container")
+	if err := cmd.Parse(args); err != nil {
+		return nil
+	}
+	if cmd.NArg() != 1 {
+		cmd.Usage()
+		return nil
+	}
+	body, _, err := cli.call("GET", "/containers/"+cmd.Arg(0)+"/proc", nil)
+	if err != nil {
+		return err
+	}
+	var procs []APIProc
+	err = json.Unmarshal(body, &procs)
+	if err != nil {
+		return err
+	}
+	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
+	fmt.Fprintln(w, "PID\tTTY\tTIME\tCMD")
+	for _, proc := range procs {
+		fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", proc.PID, proc.Tty, proc.Time, proc.Cmd)
+	}
+	w.Flush()
+	return nil
+}
+
 func (cli *DockerCli) CmdPort(args ...string) error {
 	cmd := Subcmd("port", "CONTAINER PRIVATE_PORT", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT")
 	if err := cmd.Parse(args); err != nil {

+ 36 - 0
server.go

@@ -1,6 +1,7 @@
 package docker
 
 import (
+	"bufio"
 	"errors"
 	"fmt"
 	"github.com/dotcloud/docker/auth"
@@ -12,6 +13,7 @@ import (
 	"net/http"
 	"net/url"
 	"os"
+	"os/exec"
 	"path"
 	"runtime"
 	"strings"
@@ -247,6 +249,40 @@ func (srv *Server) ImageHistory(name string) ([]APIHistory, error) {
 
 }
 
+func (srv *Server) ContainerProc(name string) ([]APIProc, error) {
+	if container := srv.runtime.Get(name); container != nil {
+		output, err := exec.Command("lxc-ps", "--name", container.ID).CombinedOutput()
+		if err != nil {
+			return nil, fmt.Errorf("Error trying to use lxc-ps: %s (%s)", err, output)
+		}
+		var procs []APIProc
+		for i, line := range strings.Split(string(output), "\n") {
+			if i == 0 || len(line) == 0 {
+				continue
+			}
+			proc := APIProc{}
+			scanner := bufio.NewScanner(strings.NewReader(line))
+			scanner.Split(bufio.ScanWords)
+			if !scanner.Scan() {
+				return nil, fmt.Errorf("Error trying to use lxc-ps")
+			}
+			// no scanner.Text because we skip container id
+			scanner.Scan()
+			proc.PID = scanner.Text()
+			scanner.Scan()
+			proc.Tty = scanner.Text()
+			scanner.Scan()
+			proc.Time = scanner.Text()
+			scanner.Scan()
+			proc.Cmd = scanner.Text()
+			procs = append(procs, proc)
+		}
+		return procs, nil
+
+	}
+	return nil, fmt.Errorf("No such container: %s", name)
+}
+
 func (srv *Server) ContainerChanges(name string) ([]Change, error) {
 	if container := srv.runtime.Get(name); container != nil {
 		return container.Changes()

+ 1 - 1
utils/utils.go

@@ -78,7 +78,7 @@ func (r *progressReader) Read(p []byte) (n int, err error) {
 	read, err := io.ReadCloser(r.reader).Read(p)
 	r.readProgress += read
 
-	updateEvery := 1024*512 //512kB
+	updateEvery := 1024 * 512 //512kB
 	if r.readTotal > 0 {
 		// Update progress for every 1% read if 1% < 512kB
 		if increment := int(0.01 * float64(r.readTotal)); increment < updateEvery {